From: Tarun Karela Date: Tue, 24 Sep 2019 15:33:02 +0000 (+0100) Subject: [RAMEN9610-20413][9610] [9630] wlbt: Delete SCSC drivers before update X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=a690fd2f258557f77de63b5cb44be1e4ad1dedde;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [RAMEN9610-20413][9610] [9630] wlbt: Delete SCSC drivers before update Remove existing SCSC drivers before applying update Change-Id: Ia9b0382ae916227a19498733ac362e8fdf752066 SCSC-Bug-Id: Rels-3171 Signed-off-by: Tarun Karela --- diff --git a/drivers/misc/samsung/Kconfig b/drivers/misc/samsung/Kconfig deleted file mode 100644 index 7a0ed3b0ea3b..000000000000 --- a/drivers/misc/samsung/Kconfig +++ /dev/null @@ -1,4 +0,0 @@ -source "drivers/misc/samsung/gpio_debug/Kconfig" -source "drivers/misc/samsung/scsc/Kconfig" -source "drivers/misc/samsung/scsc_bt/Kconfig" -source "drivers/misc/samsung/kic/Kconfig" diff --git a/drivers/misc/samsung/Makefile b/drivers/misc/samsung/Makefile deleted file mode 100644 index c4fa7425b196..000000000000 --- a/drivers/misc/samsung/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# Needed since this subdir is symlinked in the main Kernel tree -# without this our samsung subdir is NOT cleaned. -clean-files := built-in.o - -obj-$(CONFIG_GPIO_DEBUG) += gpio_debug/ -obj-$(CONFIG_SAMSUNG_KIC) += kic/ -obj-$(CONFIG_SCSC_CORE) += scsc/ -obj-$(CONFIG_SCSC_BT) += scsc_bt/ diff --git a/drivers/misc/samsung/gpio_debug/Kconfig b/drivers/misc/samsung/gpio_debug/Kconfig deleted file mode 100644 index 05d49e33d705..000000000000 --- a/drivers/misc/samsung/gpio_debug/Kconfig +++ /dev/null @@ -1,3 +0,0 @@ -config GPIO_DEBUG - tristate "GPIO debug functionality" - diff --git a/drivers/misc/samsung/gpio_debug/Makefile b/drivers/misc/samsung/gpio_debug/Makefile deleted file mode 100644 index ec13da512364..000000000000 --- a/drivers/misc/samsung/gpio_debug/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_GPIO_DEBUG) += gpio_debug.o diff --git a/drivers/misc/samsung/gpio_debug/gpio_debug.c b/drivers/misc/samsung/gpio_debug/gpio_debug.c deleted file mode 100644 index 26dbecccb5b2..000000000000 --- a/drivers/misc/samsung/gpio_debug/gpio_debug.c +++ /dev/null @@ -1,427 +0,0 @@ -/* Copyright (c) 2014 Samsung Electronics Co., Ltd */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct gpio_debug_data; - -struct gpio_debug_event { - int gpio; - int gpio_idx; - struct gpio_debug_event_def def; - struct gpio_debug_data *data; - struct dentry *file; -}; - -struct gpio_debug_data { - int gpio_count; - int *gpios; - struct dentry *gpio_debug_dir; - struct dentry *gpio_debug_events_dir; - struct platform_device *pdev; - struct gpio_debug_event *events; - int event_count; - int event_base; -}; - -static struct gpio_debug_data debug_data; - -DEFINE_MUTEX(debug_lock); - -enum { - GPIO_DEBUG_TOGGLE_100, - GPIO_DEBUG_TOGGLE_200, -}; - -static struct gpio_debug_event_def debug_events_table[] = { - [GPIO_DEBUG_TOGGLE_100] = { - .name = "toggle100", - .description = "Toggle the GPIO 100 times at initialisation", - }, - [GPIO_DEBUG_TOGGLE_200] = { - .name = "toggle200", - .description = "Toggle the GPIO 200 times at initialisation", - }, -}; - -static void gpio_debug_event(int gpio, int state) -{ - if (gpio >= 0) - gpio_set_value(gpio, state); -} - -static void gpio_debug_event_exec(int event_id, int state) -{ - if ((event_id >= 0) && (event_id < debug_data.event_count) && debug_data.events) - gpio_debug_event(debug_data.events[event_id].gpio, state); -} - -void gpio_debug_event_enter(int base, int id) -{ - gpio_debug_event_exec(base + id, 0); -} - -void gpio_debug_event_exit(int base, int id) -{ - gpio_debug_event_exec(base + id, 1); -} - -int gpio_debug_event_enabled(int base, int id) -{ - int event_id = base + id; - - if ((event_id >= 0) && - (event_id < debug_data.event_count) && - debug_data.events && - debug_data.events[event_id].gpio >= 0) - return 1; - else - return 0; -} - -static int gpio_debug_event_link(struct gpio_debug_event *event, int gpio_index) -{ - struct gpio_debug_data *data = event->data; - - if (gpio_index >= data->gpio_count) - return -ERANGE; - - if (gpio_index >= 0) - event->gpio = data->gpios[gpio_index]; - else - event->gpio = -1; - - event->gpio_idx = gpio_index; - - return 0; -} - -static ssize_t event_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - ssize_t ret = 0; - struct gpio_debug_event *event = file->f_inode->i_private; - char buf[256]; - int pos; - - mutex_lock(&debug_lock); - - pos = snprintf(buf, sizeof(buf), "Description:\n%s\n\nEvent is mapped to GPIO index %d with number %d\n", event->def.description, event->gpio_idx, event->gpio); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - - mutex_unlock(&debug_lock); - - return ret; -} - -static ssize_t event_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - char *user_string; - ssize_t ret; - struct gpio_debug_event *event = file->f_inode->i_private; - int new_index = -1; - - mutex_lock(&debug_lock); - - user_string = kmalloc(count + 1, GFP_KERNEL); - memory_read_from_buffer(user_string, count, ppos, user_buf, count); - - user_string[count] = '\0'; - ret = (ssize_t)strnlen(user_string, count + 1); - - if (kstrtou32(user_string, 10, &new_index)) { - return -EINVAL; - - gpio_debug_event_link(event, new_index); - - kfree(user_string); - mutex_unlock(&debug_lock); - - return ret; -} - -static const struct file_operations event_ops = { - .read = event_read, - .write = event_write, -}; - -static void create_event_file(struct gpio_debug_event *event) -{ - struct gpio_debug_data *data = event->data; - - if (data && data->gpio_debug_events_dir) { - event->file = debugfs_create_file(event->def.name, 0660, data->gpio_debug_events_dir, event, &event_ops); - if (IS_ERR_OR_NULL(event->file)) { - event->file = NULL; - pr_warn("%s: Could not create debugfs file for %s\n", __func__, event->def.name); - } - } -} - -static void remove_event_file(struct gpio_debug_event *event) -{ - if (event && event->file) { - debugfs_remove(event->file); - event->file = NULL; - } -} - -static void gpio_debug_init_event(struct gpio_debug_data *data, struct gpio_debug_event_def *event, struct gpio_debug_event *event_save) -{ - event_save->def.description = event->description; - event_save->def.name = event->name; - event_save->gpio = -1; - event_save->gpio_idx = -1; - event_save->data = data; - - create_event_file(event_save); -} - -static void gpio_debug_destroy_event(struct gpio_debug_event *event) -{ - remove_event_file(event); - event->def.description = NULL; - event->def.name = NULL; - event->gpio = -1; - event->gpio_idx = -1; - event->data = NULL; -} - -int gpio_debug_event_list_register(struct gpio_debug_event_def *events, int event_count) -{ - struct gpio_debug_data *data = &debug_data; - int start_index = data->event_count; - struct gpio_debug_event *new_events; - int new_event_count = data->event_count + event_count; - int i, j; - - mutex_lock(&debug_lock); - - if (data->events) - for (i = 0; i < data->event_count; i++) - remove_event_file(&data->events[i]); - - new_events = krealloc(data->events, new_event_count * sizeof(struct gpio_debug_event), GFP_KERNEL); - if (!new_events) { - pr_warn("%s: Could not expand for extra events\n", __func__); - /* If krealloc fails, data->events is unchanged, so just exit */ - return -ENOMEM; - } - data->events = new_events; - for (i = 0; i < data->event_count; i++) - create_event_file(&data->events[i]); - - data->event_count = new_event_count; - - for (i = 0, j = start_index; (i < event_count) && (j < data->event_count); i++, j++) - gpio_debug_init_event(data, &events[i], &data->events[j]); - - mutex_unlock(&debug_lock); - return start_index; -} - -void gpio_debug_event_list_unregister(int base, int event_count) -{ - int i; - struct gpio_debug_data *data = &debug_data; - - mutex_lock(&debug_lock); - - for (i = base; (i < (event_count + base)) && (i < data->event_count); i++) - gpio_debug_destroy_event(&data->events[i]); - - mutex_unlock(&debug_lock); -} - -static ssize_t event_list_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - int i; - ssize_t ret = 0; - int length = 0; - char *buf; - struct gpio_debug_data *data = file->f_inode->i_private; - struct device *dev = &data->pdev->dev; - char headline[] = " gpio event\n"; - - mutex_lock(&debug_lock); - - length += strlen(headline); - - for (i = 0; i < data->event_count; i++) - if (data->events[i].def.name) - length += strlen(data->events[i].def.name) + 7; - length++; /* Reserve space for NULL termination */ - - buf = devm_kzalloc(dev, length, GFP_KERNEL); - buf[0] = '\0'; - snprintf(buf, length, "%s", headline); - for (i = 0; i < data->event_count; i++) - if (data->events[i].data) { - if (data->events[i].gpio_idx >= 0) - snprintf(buf, length, "%s%5d %s\n", buf, data->events[i].gpio_idx, data->events[i].def.name); - else - snprintf(buf, length, "%s %s\n", buf, data->events[i].def.name); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, length); - devm_kfree(dev, buf); - - mutex_unlock(&debug_lock); - - return ret; -} - -static const struct file_operations event_list_ops = { - .read = event_list_read, -}; - -static ssize_t num_gpios_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - ssize_t ret = 0; - struct gpio_debug_data *data = file->f_inode->i_private; - char buf[256]; - int pos; - - pos = snprintf(buf, sizeof(buf), "%d\n", data->gpio_count); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; -} - -static const struct file_operations num_gpios_ops = { - .read = num_gpios_read, -}; - -static int gpio_debug_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct device *dev = &pdev->dev; - int count; - struct gpio_debug_data *data = &debug_data; - int i, j; - - mutex_lock(&debug_lock); - - count = of_gpio_count(np); - if (count < 0) - count = 0; /* Errors register as no GPIOs available */ - - data->gpio_count = count; - data->gpios = NULL; - data->pdev = pdev; - - if (count) { - data->gpios = devm_kzalloc(dev, count * sizeof(int), GFP_KERNEL); - for (i = 0; i < count; i++) { - data->gpios[i] = of_get_gpio(np, i); - dev_info(dev, "GPIO at index %d has number %d\n", i, data->gpios[i]); - if (gpio_is_valid(data->gpios[i])) { - char label[256]; - - sprintf(label, "debug-gpio-%d", i); - dev_info(dev, "Requesting GPIO %d index %d with label %s\n", data->gpios[i], i, label); - if (devm_gpio_request(dev, data->gpios[i], label)) - dev_err(dev, "GPIO [%d] request failed\n", data->gpios[i]); - gpio_set_value(data->gpios[i], 1); - } else - dev_warn(dev, "GPIO at index %d is invalid\n", i); - } - } - - data->gpio_debug_dir = debugfs_create_dir("gpio_debug", NULL); - if (!IS_ERR_OR_NULL(data->gpio_debug_dir)) { - data->gpio_debug_events_dir = debugfs_create_dir("events", data->gpio_debug_dir); - if (IS_ERR_OR_NULL(data->gpio_debug_events_dir)) { - data->gpio_debug_events_dir = NULL; - dev_err(dev, "Debugfs cannot create subdir\n"); - } - debugfs_create_file("event_list", 0440, data->gpio_debug_dir, data, &event_list_ops); - debugfs_create_file("num_gpios", 0440, data->gpio_debug_dir, data, &num_gpios_ops); - } else { - data->gpio_debug_dir = NULL; - dev_warn(dev, "Debugfs is not available, configuration of GPIO debug is not possible\n"); - } - - for (i = 0; i < data->event_count; i++) - create_event_file(&data->events[i]); - - mutex_unlock(&debug_lock); - - data->event_base = gpio_debug_event_list_register(debug_events_table, ARRAY_SIZE(debug_events_table)); - - for (i = 0; i < count; i++) { - gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_100], i); - for (j = 0; j < 100; j++) { - gpio_debug_event_enter(data->event_base, GPIO_DEBUG_TOGGLE_100); - gpio_debug_event_exit(data->event_base, GPIO_DEBUG_TOGGLE_100); - } - } - gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_100], -1); - - for (i = 0; i < count; i++) { - gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_200], i); - for (j = 0; j < 200; j++) { - gpio_debug_event_enter(data->event_base, GPIO_DEBUG_TOGGLE_200); - gpio_debug_event_exit(data->event_base, GPIO_DEBUG_TOGGLE_200); - } - } - gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_200], -1); - - return 0; -} - -static int gpio_debug_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct gpio_debug_data *data = &debug_data; - - mutex_lock(&debug_lock); - debugfs_remove_recursive(data->gpio_debug_dir); - data->gpio_debug_dir = NULL; - data->gpio_debug_events_dir = NULL; - - if (data->gpios) { - int i; - - for (i = 0; i < data->gpio_count; i++) - if (gpio_is_valid(data->gpios[i])) - devm_gpio_free(dev, data->gpios[i]); - devm_kfree(dev, data->gpios); - data->gpios = NULL; - data->gpio_count = 0; - } - data->pdev = NULL; - kfree(data->events); - data->events = NULL; - data->event_count = 0; - mutex_unlock(&debug_lock); - - return 0; -} - -static const struct of_device_id gpio_debug_match[] = { - { .compatible = "samsung,gpio-debug", }, - {}, -}; -MODULE_DEVICE_TABLE(of, gpio_debug_match); - -static struct platform_driver gpio_debug_driver = { - .probe = gpio_debug_probe, - .remove = gpio_debug_remove, - .driver = { - .name = "gpio_debug", - .of_match_table = gpio_debug_match, - } -}; -module_platform_driver(gpio_debug_driver); - -MODULE_DESCRIPTION("GPIO Debug framework"); -MODULE_AUTHOR("Samsung Electronics Co., Ltd"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/misc/samsung/kic/Kconfig b/drivers/misc/samsung/kic/Kconfig deleted file mode 100644 index 0851fb06ee99..000000000000 --- a/drivers/misc/samsung/kic/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config SAMSUNG_KIC - tristate "Kernel Information and Control (KIC) interface for Samsung Wi-Fi and Bluetooth chips" - -if SAMSUNG_KIC != n - -config SLSI_KIC_API_ENABLED - bool "Enable the KIC kernel API" - depends on SAMSUNG_KIC -endif diff --git a/drivers/misc/samsung/kic/Makefile b/drivers/misc/samsung/kic/Makefile deleted file mode 100644 index f865ef35c939..000000000000 --- a/drivers/misc/samsung/kic/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -obj-$(CONFIG_SAMSUNG_KIC) += samsung_kic.o -samsung_kic-y += \ - slsi_kic_core.o \ - slsi_kic_filtering.o \ - slsi_kic_sap_wifi.o \ - slsi_kic_sap_cm.o \ - slsi_kic_sap_bt.o \ - slsi_kic_sap_ant.o - -ccflags-y += $(CONFIG_SAMSUNG_KIC_EXTRA) - -# ---------------------------------------------------------------------------- -# KIC configuration -# ---------------------------------------------------------------------------- - -ccflags-$(CONFIG_SLSI_KIC_API_ENABLED) += -DCONFIG_SLSI_KIC_API_ENABLED - -ccflags-$(CONFIG_SCSC_LOGRING) += -DCONFIG_SCSC_PRINTK diff --git a/drivers/misc/samsung/kic/slsi_kic_core.c b/drivers/misc/samsung/kic/slsi_kic_core.c deleted file mode 100755 index 1f90614ecedf..000000000000 --- a/drivers/misc/samsung/kic/slsi_kic_core.c +++ /dev/null @@ -1,793 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include "slsi_kic_internal.h" - -static DEFINE_MUTEX(kic_lock); -static struct slsi_kic_pdata *pdata; - -#define SLSI_MAX_NUM_KIC_OPS 7 -#define SLSI_MAX_NUM_MULTICAST_GROUP 1 - -static struct genl_ops slsi_kic_ops[SLSI_MAX_NUM_KIC_OPS]; - -static int slsi_kic_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info) -{ - SCSC_TAG_ERR(KIC_COMMON, "%s Handle CMD %d, seq %d\n", - __func__, ops->cmd, info->snd_seq); - - OS_UNUSED_PARAMETER(skb); - - /* Called BEFORE the command cb - do filtering here */ - - /* Consider doing some check for "test_mode" primitives here: - * It could be a way to prevent test primitives (which can be - * powerful) to run unless test_mode has been configured. */ - - return 0; -} - -static void slsi_kic_post_doit(const struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info) -{ - OS_UNUSED_PARAMETER(ops); - OS_UNUSED_PARAMETER(skb); - OS_UNUSED_PARAMETER(info); - - /* Called AFTER the command cb - could do something here */ -} - -static const struct genl_multicast_group slsi_kic_general_system_mcgrp[SLSI_MAX_NUM_MULTICAST_GROUP] = { - { .name = "general_system", }, -}; - - -/* The netlink family */ -static struct genl_family slsi_kic_fam = { - .name = "slsi_kic", /* Have users key off the name instead */ - .hdrsize = 0, /* No private header */ - .version = 2, - .netnsok = true, - .maxattr = SLSI_KIC_ATTR_MAX, - .pre_doit = slsi_kic_pre_doit, - .post_doit = slsi_kic_post_doit, - .ops = slsi_kic_ops, - .n_ops = SLSI_MAX_NUM_KIC_OPS, - .mcgrps = slsi_kic_general_system_mcgrp, - .n_mcgrps = SLSI_MAX_NUM_MULTICAST_GROUP, -}; - -/** - * Message building helpers - */ -static inline void *kic_hdr_put(struct sk_buff *skb, uint32_t portid, uint32_t seq, - int flags, u8 cmd) -{ - /* Since there is no private header just add the generic one */ - return genlmsg_put(skb, portid, seq, &slsi_kic_fam, flags, cmd); -} - -static int kic_build_u32_msg(struct sk_buff *msg, uint32_t portid, uint32_t seq, int flags, - enum slsi_kic_commands cmd, int attrtype, uint32_t payload) -{ - void *hdr; - - hdr = kic_hdr_put(msg, portid, seq, flags, cmd); - if (!hdr) - return -EFAULT; - - if (nla_put_u32(msg, attrtype, payload)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - - return 0; - -nla_put_failure: - genlmsg_cancel(msg, hdr); - return -EMSGSIZE; -} - -static int kic_add_timestamp_attrs(struct sk_buff *msg) -{ - struct timespec ts; - - /** - * Use getrawmonotonic instead of getnstimeofday to avoid problems with - * NTP updating things, which can make things look weird. - */ - getrawmonotonic(&ts); - - if (nla_put_u64_64bit(msg, SLSI_KIC_ATTR_TIMESTAMP_TV_SEC, ts.tv_sec, IFLA_BR_PAD)) - goto nla_put_failure; - - if (nla_put_u64_64bit(msg, SLSI_KIC_ATTR_TIMESTAMP_TV_NSEC, ts.tv_nsec, IFLA_BR_PAD)) - goto nla_put_failure; - - return 0; - -nla_put_failure: - return -EMSGSIZE; -} - -static int kic_build_system_event_msg(struct sk_buff *msg, uint32_t portid, - uint32_t seq, int flags, - uint32_t event_cat, uint32_t event) -{ - void *hdr; - struct nlattr *nla; - - hdr = kic_hdr_put(msg, portid, seq, flags, SLSI_KIC_CMD_SYSTEM_EVENT_IND); - if (!hdr) - return -EFAULT; - - nla = nla_nest_start(msg, SLSI_KIC_ATTR_TIMESTAMP); - if (kic_add_timestamp_attrs(msg) < 0) - nla_nest_cancel(msg, nla); - else - nla_nest_end(msg, nla); - - if (nla_put_u32(msg, SLSI_KIC_ATTR_SYSTEM_EVENT_CATEGORY, event_cat)) - goto nla_put_failure; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_SYSTEM_EVENT, event)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - - return 0; - -nla_put_failure: - genlmsg_cancel(msg, hdr); - return -EMSGSIZE; -} - - -static int kic_build_firmware_event_msg(struct sk_buff *msg, uint32_t portid, - uint32_t seq, int flags, - uint16_t firmware_event_type, - enum slsi_kic_technology_type tech_type, - uint32_t contain_type, - struct slsi_kic_firmware_event_ccp_host *event) -{ - void *hdr; - struct nlattr *nla; - - hdr = kic_hdr_put(msg, portid, seq, flags, SLSI_KIC_CMD_FIRMWARE_EVENT_IND); - if (!hdr) { - nlmsg_free(msg); - return -EFAULT; - } - - if (nla_put_u16(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_TYPE, firmware_event_type)) - goto nla_put_failure; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_TECHNOLOGY_TYPE, tech_type)) - goto nla_put_failure; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_FIRMWARE_CONTAINER_TYPE, contain_type)) - goto nla_put_failure; - - nla = nla_nest_start(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CONTAINER_CCP_HOST); - if (nla_put_u32(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_ID, event->id)) - goto nla_put_failure_cancel; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_LEVEL, event->level)) - goto nla_put_failure_cancel; - - if (nla_put_string(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_LEVEL_STRING, event->level_string)) - goto nla_put_failure_cancel; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_TIMESTAMP, event->timestamp)) - goto nla_put_failure_cancel; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_CPU, event->cpu)) - goto nla_put_failure_cancel; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_OCCURENCES, event->occurences)) - goto nla_put_failure_cancel; - - if (nla_put(msg, SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_ARG, event->arg_length, event->arg)) - goto nla_put_failure_cancel; - nla_nest_end(msg, nla); - - genlmsg_end(msg, hdr); - - return 0; - -nla_put_failure_cancel: - nla_nest_cancel(msg, nla); - -nla_put_failure: - genlmsg_cancel(msg, hdr); - return -EMSGSIZE; -} - - -static int kic_build_service_info_msg_add_service(struct sk_buff *msg, - enum slsi_kic_technology_type tech, - struct slsi_kic_service_info *info) -{ - struct nlattr *nla = NULL; - - if (!msg || !info) - goto nla_put_failure; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_TECHNOLOGY_TYPE, tech)) - goto nla_put_failure; - - nla = nla_nest_start(msg, SLSI_KIC_ATTR_SERVICE_INFO); - if (nla_put_string(msg, SLSI_KIC_ATTR_SERVICE_INFO_VER_STR, info->ver_str)) - goto nla_put_failure; - - if (nla_put_u16(msg, SLSI_KIC_ATTR_SERVICE_INFO_FW_API_MAJOR, info->fw_api_major)) - goto nla_put_failure; - - if (nla_put_u16(msg, SLSI_KIC_ATTR_SERVICE_INFO_FW_API_MINOR, info->fw_api_minor)) - goto nla_put_failure; - - if (nla_put_u16(msg, SLSI_KIC_ATTR_SERVICE_INFO_RELEASE_PRODUCT, info->release_product)) - goto nla_put_failure; - - if (nla_put_u16(msg, SLSI_KIC_ATTR_SERVICE_INFO_HOST_RELEASE_ITERATION, info->host_release_iteration)) - goto nla_put_failure; - - if (nla_put_u16(msg, SLSI_KIC_ATTR_SERVICE_INFO_HOST_RELEASE_CANDIDATE, info->host_release_candidate)) - goto nla_put_failure; - - nla_nest_end(msg, nla); - - return 0; - -nla_put_failure: - if (nla) - nla_nest_cancel(msg, nla); - - return -EMSGSIZE; -} - -static int kic_build_service_info_msg(struct sk_buff *msg, uint32_t portid, - uint32_t seq, int flags, - enum slsi_kic_technology_type tech, - struct slsi_kic_service_info *info) -{ - void *hdr; - - hdr = kic_hdr_put(msg, portid, seq, flags, SLSI_KIC_CMD_SERVICE_INFORMATION_IND); - if (!hdr) - return -EFAULT; - - if (kic_build_service_info_msg_add_service(msg, tech, info) < 0) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - - return 0; - -nla_put_failure: - genlmsg_cancel(msg, hdr); - return -EMSGSIZE; -} - - -static int get_snd_pid(struct genl_info *info) -{ - uint32_t snd_pid = 0; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) - snd_pid = info->snd_pid; -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 6, 0) - snd_pid = info->snd_portid; -#endif - - return snd_pid; -} - -struct slsi_kic_pdata *slsi_kic_core_get_context(void) -{ - return pdata; -} - -/** - * Set the record to NULL to free and delete all stored records. - */ -static int service_info_delete_record(struct slsi_kic_service_details *record) -{ - struct slsi_kic_pdata *pdata = slsi_kic_core_get_context(); - - if (!pdata) - return -EINVAL; - - if (down_interruptible(&pdata->chip_details.proxy_service_list_mutex)) - SCSC_TAG_ERR(KIC_COMMON, "Failed to lock service info mutex - continue anyway\n"); - - if (record == NULL) { - struct slsi_kic_service_details *service, *tmp_node; - - list_for_each_entry_safe(service, tmp_node, &pdata->chip_details.proxy_service_list, proxy_q) { - list_del(&service->proxy_q); - kfree(service); - } - } else { - list_del(&record->proxy_q); - kfree(record); - } - up(&pdata->chip_details.proxy_service_list_mutex); - - return 0; -} - -static struct slsi_kic_service_details * -service_info_find_entry(enum slsi_kic_technology_type tech) -{ - struct slsi_kic_pdata *pdata = slsi_kic_core_get_context(); - struct slsi_kic_service_details *service, *tmp_node; - - if (!pdata) - return NULL; - - list_for_each_entry_safe(service, tmp_node, &pdata->chip_details.proxy_service_list, proxy_q) { - if (service->tech == tech) - return service; - } - - return NULL; -} - -static int service_info_update_record(enum slsi_kic_technology_type tech, - struct slsi_kic_service_info *info) -{ - struct slsi_kic_pdata *pdata = slsi_kic_core_get_context(); - static struct slsi_kic_service_details *record; - - if (!pdata) - return -EINVAL; - - if (down_interruptible(&pdata->chip_details.proxy_service_list_mutex)) - goto err_out; - - record = service_info_find_entry(tech); - if (record == NULL) { - up(&pdata->chip_details.proxy_service_list_mutex); - goto err_out; - } - - record->tech = tech; - memcpy(&record->info, info, sizeof(struct slsi_kic_service_info)); - up(&pdata->chip_details.proxy_service_list_mutex); - - return 0; - -err_out: - SCSC_TAG_ERR(KIC_COMMON, "Failed to update service info record\n"); - return -EFAULT; -} - -static int service_info_add(enum slsi_kic_technology_type tech, - struct slsi_kic_service_info *info) -{ - struct slsi_kic_service_details *new_entry; - struct slsi_kic_pdata *pdata = slsi_kic_core_get_context(); - - if (!pdata) - return -EINVAL; - - new_entry = kmalloc(sizeof(struct slsi_kic_service_details), GFP_KERNEL); - if (!new_entry) - return -ENOMEM; - - new_entry->tech = tech; - memcpy(&new_entry->info, info, sizeof(struct slsi_kic_service_info)); - - if (down_interruptible(&pdata->chip_details.proxy_service_list_mutex)) - goto err_out; - - list_add_tail(&new_entry->proxy_q, &pdata->chip_details.proxy_service_list); - up(&pdata->chip_details.proxy_service_list_mutex); - - return 0; - -err_out: - SCSC_TAG_ERR(KIC_COMMON, "Failed to add service info record to list\n"); - kfree(new_entry); - return -EFAULT; -} - - -/** - * Command callbacks - */ - -/* This function shall not do anything since the direction is - * kernel->user space for this primitive. We should look into if it's - * possible to handle this better than having an empty stub function. */ -static int slsi_kic_wrong_direction(struct sk_buff *skb, struct genl_info *info) -{ - OS_UNUSED_PARAMETER(skb); - - SCSC_TAG_ERR(KIC_COMMON, "%s Received CMD from pid %u seq %u: Wrong direction only supports kernel->user space\n", - __func__, info->snd_seq, get_snd_pid(info)); - return -EINVAL; -} - -static int slsi_kic_interface_version_number_req(struct sk_buff *skb, struct genl_info *info) -{ - struct sk_buff *msg; - void *hdr; - - OS_UNUSED_PARAMETER(skb); - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - hdr = kic_hdr_put(msg, 0, info->snd_seq, 0, SLSI_KIC_CMD_KIC_INTERFACE_VERSION_NUMBER_REQ); - if (!hdr) - goto nl_hdr_failure; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_KIC_VERSION_MAJOR, SLSI_KIC_INTERFACE_VERSION_MAJOR)) - goto nla_put_failure; - - if (nla_put_u32(msg, SLSI_KIC_ATTR_KIC_VERSION_MINOR, SLSI_KIC_INTERFACE_VERSION_MINOR)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - return genlmsg_reply(msg, info); - -nla_put_failure: - genlmsg_cancel(msg, hdr); - -nl_hdr_failure: - nlmsg_free(msg); - return -ENOBUFS; -} - -static int slsi_kic_echo_req(struct sk_buff *skb, struct genl_info *info) -{ - struct sk_buff *msg; - uint32_t payload = 0; - - OS_UNUSED_PARAMETER(skb); - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - if (info->attrs[SLSI_KIC_ATTR_ECHO]) - payload = nla_get_u32(info->attrs[SLSI_KIC_ATTR_ECHO]); - - if (kic_build_u32_msg(msg, get_snd_pid(info), info->snd_seq, 0, - SLSI_KIC_CMD_ECHO_REQ, SLSI_KIC_ATTR_ECHO, payload) < 0) { - nlmsg_free(msg); - return -ENOBUFS; - } - - return genlmsg_reply(msg, info); -} - -static int slsi_kic_service_information_req(struct sk_buff *skb, struct genl_info *info) -{ - struct slsi_kic_pdata *pdata = slsi_kic_core_get_context(); - int counter = 0, i; - struct sk_buff *msg; - struct slsi_kic_service_details *sr; - void *hdr; - - OS_UNUSED_PARAMETER(skb); - - if (!pdata) - return -EINVAL; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - hdr = kic_hdr_put(msg, 0, info->snd_seq, 0, SLSI_KIC_CMD_SERVICE_INFORMATION_REQ); - if (!hdr) - goto nla_put_failure; - - if (down_interruptible(&pdata->chip_details.proxy_service_list_mutex)) - goto nla_put_failure; - - /* The request doesn't carry attributes, so no validation required. - * Query the list for information for each technology and encode. */ - for (i = 0; i < slsi_kic_technology_type__after_last; i++) { - sr = service_info_find_entry(i); - if (sr) { - counter++; - if (kic_build_service_info_msg_add_service(msg, i, &sr->info) < 0) { - up(&pdata->chip_details.proxy_service_list_mutex); - goto nla_put_failure; - } - } - } - up(&pdata->chip_details.proxy_service_list_mutex); - - if (nla_put_u32(msg, SLSI_KIC_ATTR_NUMBER_OF_ENCODED_SERVICES, counter)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - return genlmsg_reply(msg, info); - -nla_put_failure: - nlmsg_free(msg); - return -EMSGSIZE; -} - -static int slsi_kic_test_trigger_recovery_req(struct sk_buff *skb, struct genl_info *info) -{ - struct sk_buff *msg; - uint32_t technology = 0, recovery_type = 0; - struct slsi_kic_pdata *pdata = slsi_kic_core_get_context(); - enum slsi_kic_test_recovery_status status = slsi_kic_test_recovery_status_ok; - - OS_UNUSED_PARAMETER(skb); - - if (info->attrs[SLSI_KIC_ATTR_TECHNOLOGY_TYPE]) - technology = nla_get_u32(info->attrs[SLSI_KIC_ATTR_TECHNOLOGY_TYPE]); - - if (info->attrs[SLSI_KIC_ATTR_TEST_RECOVERY_TYPE]) - recovery_type = nla_get_u32(info->attrs[SLSI_KIC_ATTR_TEST_RECOVERY_TYPE]); - - if (pdata) { - int err = -EFAULT; - - if (technology == slsi_kic_technology_type_wifi) { - struct slsi_kic_wifi_ops_tuple *wifi_ops = NULL; - - wifi_ops = &pdata->wifi_ops_tuple; - - mutex_lock(&wifi_ops->ops_mutex); - if (wifi_ops->wifi_ops.trigger_recovery) - err = wifi_ops->wifi_ops.trigger_recovery(wifi_ops->priv, - (enum slsi_kic_test_recovery_type)recovery_type); - mutex_unlock(&wifi_ops->ops_mutex); - } else if (technology == slsi_kic_technology_type_curator) { - struct slsi_kic_cm_ops_tuple *cm_ops = NULL; - - cm_ops = &pdata->cm_ops_tuple; - - mutex_lock(&cm_ops->ops_mutex); - if (cm_ops->cm_ops.trigger_recovery) - err = cm_ops->cm_ops.trigger_recovery(cm_ops->priv, - (enum slsi_kic_test_recovery_type)recovery_type); - mutex_unlock(&cm_ops->ops_mutex); - } else if (technology == slsi_kic_technology_type_bt) { - struct slsi_kic_bt_ops_tuple *bt_ops = NULL; - - bt_ops = &pdata->bt_ops_tuple; - - mutex_lock(&bt_ops->ops_mutex); - if (bt_ops->bt_ops.trigger_recovery) - err = bt_ops->bt_ops.trigger_recovery(bt_ops->priv, - (enum slsi_kic_test_recovery_type)recovery_type); - mutex_unlock(&bt_ops->ops_mutex); - } else if (technology == slsi_kic_technology_type_ant) { - struct slsi_kic_ant_ops_tuple *ant_ops = NULL; - - ant_ops = &pdata->ant_ops_tuple; - - mutex_lock(&ant_ops->ops_mutex); - if (ant_ops->ant_ops.trigger_recovery) - err = ant_ops->ant_ops.trigger_recovery(ant_ops->priv, - (enum slsi_kic_test_recovery_type)recovery_type); - mutex_unlock(&ant_ops->ops_mutex); - } - - if (err < 0) - status = slsi_kic_test_recovery_status_error_send_msg; - } else - status = slsi_kic_test_recovery_status_error_invald_param; - - /* Prepare reply */ - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - if (kic_build_u32_msg(msg, get_snd_pid(info), info->snd_seq, 0, - SLSI_KIC_CMD_TEST_TRIGGER_RECOVERY_REQ, SLSI_KIC_ATTR_TRIGGER_RECOVERY_STATUS, status) < 0) - goto nl_hdr_failure; - - return genlmsg_reply(msg, info); - -nl_hdr_failure: - nlmsg_free(msg); - return -ENOBUFS; -} - - -int slsi_kic_service_information_ind(enum slsi_kic_technology_type tech, - struct slsi_kic_service_info *info) -{ - struct sk_buff *msg; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - if (service_info_find_entry(tech) == NULL) { - if (service_info_add(tech, info) < 0) - SCSC_TAG_ERR(KIC_COMMON, "%s Failed to add record\n", __func__); - } else if (service_info_update_record(tech, info) < 0) - SCSC_TAG_ERR(KIC_COMMON, "%s Failed to update record\n", __func__); - - if (kic_build_service_info_msg(msg, 0, 0, 0, tech, info) < 0) - goto err; - - return genlmsg_multicast(&slsi_kic_fam, msg, 0, 0, GFP_KERNEL); - -err: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(slsi_kic_service_information_ind); - - -int slsi_kic_system_event_ind(enum slsi_kic_system_event_category event_cat, - enum slsi_kic_system_events event, gfp_t flags) -{ - struct sk_buff *msg; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags); - if (!msg) - return -ENOMEM; - - if (kic_build_system_event_msg(msg, 0, 0, 0, event_cat, event) < 0) - goto err; - - return genlmsg_multicast(&slsi_kic_fam, msg, 0, 0, flags); - -err: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(slsi_kic_system_event_ind); - - -int slsi_kic_firmware_event_ind(uint16_t firmware_event_type, enum slsi_kic_technology_type tech_type, - uint32_t contain_type, struct slsi_kic_firmware_event_ccp_host *event) -{ - struct sk_buff *msg; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - if (kic_build_firmware_event_msg(msg, 0, 0, 0, firmware_event_type, tech_type, contain_type, event) < 0) - return -ENOBUFS; - - return genlmsg_multicast(&slsi_kic_fam, msg, 0, 0, GFP_KERNEL); -} -EXPORT_SYMBOL(slsi_kic_firmware_event_ind); - - -static struct genl_ops slsi_kic_ops[SLSI_MAX_NUM_KIC_OPS] = { - { - .cmd = SLSI_KIC_CMD_KIC_INTERFACE_VERSION_NUMBER_REQ, - .doit = slsi_kic_interface_version_number_req, - .policy = slsi_kic_attr_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = SLSI_KIC_CMD_SYSTEM_EVENT_IND, - .doit = slsi_kic_wrong_direction, - .policy = slsi_kic_attr_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = SLSI_KIC_CMD_SERVICE_INFORMATION_REQ, - .doit = slsi_kic_service_information_req, - .policy = slsi_kic_attr_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = SLSI_KIC_CMD_SERVICE_INFORMATION_IND, - .doit = slsi_kic_wrong_direction, - .policy = slsi_kic_attr_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = SLSI_KIC_CMD_FIRMWARE_EVENT_IND, - .doit = slsi_kic_wrong_direction, - .policy = slsi_kic_attr_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = SLSI_KIC_CMD_ECHO_REQ, - .doit = slsi_kic_echo_req, - .policy = slsi_kic_attr_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = SLSI_KIC_CMD_TEST_TRIGGER_RECOVERY_REQ, - .doit = slsi_kic_test_trigger_recovery_req, - .policy = slsi_kic_attr_policy, - .flags = GENL_ADMIN_PERM, - }, -}; - -static int __init slsi_kic_init(void) -{ - int err; - - SCSC_TAG_DEBUG(KIC_COMMON, "%s Enter\n", __func__); - - mutex_lock(&kic_lock); - - pdata = kzalloc(sizeof(struct slsi_kic_pdata), GFP_KERNEL); - if (!pdata) { - SCSC_TAG_ERR(KIC_COMMON, "%s Exit - no mem\n", __func__); - mutex_unlock(&kic_lock); - return -ENOMEM; - } - - mutex_init(&pdata->wifi_ops_tuple.ops_mutex); - mutex_init(&pdata->cm_ops_tuple.ops_mutex); - mutex_init(&pdata->bt_ops_tuple.ops_mutex); - mutex_init(&pdata->ant_ops_tuple.ops_mutex); - - /* Init chip information proxy list */ - INIT_LIST_HEAD(&pdata->chip_details.proxy_service_list); - sema_init(&pdata->chip_details.proxy_service_list_mutex, 1); - pdata->state = idle; - - err = genl_register_family(&slsi_kic_fam); - if (err != 0) - goto err_out; - - mutex_unlock(&kic_lock); - SCSC_TAG_DEBUG(KIC_COMMON, "%s Exit\n", __func__); - return 0; - -err_out: - genl_unregister_family(&slsi_kic_fam); - mutex_unlock(&kic_lock); - SCSC_TAG_ERR(KIC_COMMON, "%s Exit - err %d\n", __func__, err); - return err; -} - -static void __exit slsi_kic_exit(void) -{ - int err; - - SCSC_TAG_DEBUG(KIC_COMMON, "%s Enter\n", __func__); - - BUG_ON(!pdata); - if (!pdata) { - SCSC_TAG_ERR(KIC_COMMON, "%s Exit - invalid pdata\n", __func__); - return; - } - - mutex_lock(&kic_lock); - err = genl_unregister_family(&slsi_kic_fam); - if (err < 0) - SCSC_TAG_ERR(KIC_COMMON, "%s Failed to unregister family\n", __func__); - - if (service_info_delete_record(NULL) < 0) - SCSC_TAG_ERR(KIC_COMMON, "%s Deleting service info liste failed\n", __func__); - - mutex_destroy(&pdata->wifi_ops_tuple.ops_mutex); - mutex_destroy(&pdata->cm_ops_tuple.ops_mutex); - mutex_destroy(&pdata->bt_ops_tuple.ops_mutex); - mutex_destroy(&pdata->ant_ops_tuple.ops_mutex); - - kfree(pdata); - pdata = NULL; - mutex_unlock(&kic_lock); - - SCSC_TAG_DEBUG(KIC_COMMON, "%s Exit\n", __func__); -} - -module_init(slsi_kic_init); -module_exit(slsi_kic_exit); - -MODULE_DESCRIPTION("SCSC Kernel Information and Control (KIC) interface"); -MODULE_AUTHOR("Samsung Electronics Co., Ltd"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/misc/samsung/kic/slsi_kic_filtering.c b/drivers/misc/samsung/kic/slsi_kic_filtering.c deleted file mode 100644 index 93c0c2d3d79c..000000000000 --- a/drivers/misc/samsung/kic/slsi_kic_filtering.c +++ /dev/null @@ -1,8 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Implement subscriber and filtering here. This won't be essential for - * first draft of the kernel KIC implementation */ diff --git a/drivers/misc/samsung/kic/slsi_kic_internal.h b/drivers/misc/samsung/kic/slsi_kic_internal.h deleted file mode 100755 index 444ecdd0121f..000000000000 --- a/drivers/misc/samsung/kic/slsi_kic_internal.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_INTERNAL_H -#define __SLSI_KIC_INTERNAL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#define OS_UNUSED_PARAMETER(x) ((void)(x)) - -/** - * Core instance - */ -enum slsi_kic_state { - idle, - initialised, - ready -}; - -struct slsi_kic_service_details { - struct list_head proxy_q; - enum slsi_kic_technology_type tech; - struct slsi_kic_service_info info; -}; - -struct slsi_kic_chip_details { - struct semaphore proxy_service_list_mutex; - struct list_head proxy_service_list; -}; - -struct slsi_kic_wifi_ops_tuple { - void *priv; - struct slsi_kic_wifi_ops wifi_ops; - struct mutex ops_mutex; -}; - -struct slsi_kic_bt_ops_tuple { - void *priv; - struct slsi_kic_bt_ops bt_ops; - struct mutex ops_mutex; -}; - -struct slsi_kic_ant_ops_tuple { - void *priv; - struct slsi_kic_ant_ops ant_ops; - struct mutex ops_mutex; -}; - -struct slsi_kic_cm_ops_tuple { - void *priv; - struct slsi_kic_cm_ops cm_ops; - struct mutex ops_mutex; -}; - -struct slsi_kic_pdata { - enum slsi_kic_state state; - struct slsi_kic_chip_details chip_details; - struct slsi_kic_wifi_ops_tuple wifi_ops_tuple; - struct slsi_kic_cm_ops_tuple cm_ops_tuple; - struct slsi_kic_bt_ops_tuple bt_ops_tuple; - struct slsi_kic_ant_ops_tuple ant_ops_tuple; - uint32_t seq; /* This should *perhaps* be moved to a record struct for - * each subscription - will look into that during the - * filtering work. */ -}; - -struct slsi_kic_pdata *slsi_kic_core_get_context(void); - -#endif /* #ifndef __SLSI_KIC_INTERNAL_H */ diff --git a/drivers/misc/samsung/kic/slsi_kic_sap_ant.c b/drivers/misc/samsung/kic/slsi_kic_sap_ant.c deleted file mode 100755 index 2e6ec7c066d0..000000000000 --- a/drivers/misc/samsung/kic/slsi_kic_sap_ant.c +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "slsi_kic_internal.h" - -#if defined(CONFIG_SCSC_ANT) && defined(CONFIG_SAMSUNG_KIC) -int slsi_kic_ant_ops_register(void *priv, struct slsi_kic_ant_ops *ant_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - if (!kic_inst) - return -EFAULT; - - mutex_lock(&kic_inst->ant_ops_tuple.ops_mutex); - memcpy(&kic_inst->ant_ops_tuple.ant_ops, ant_ops, sizeof(struct slsi_kic_ant_ops)); - kic_inst->ant_ops_tuple.priv = priv; - mutex_unlock(&kic_inst->ant_ops_tuple.ops_mutex); - return 0; -} -EXPORT_SYMBOL(slsi_kic_ant_ops_register); - -void slsi_kic_ant_ops_unregister(struct slsi_kic_ant_ops *ant_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - OS_UNUSED_PARAMETER(ant_ops); - - if (!kic_inst) - return; - - mutex_lock(&kic_inst->ant_ops_tuple.ops_mutex); - memset(&kic_inst->ant_ops_tuple.ant_ops, 0, sizeof(struct slsi_kic_ant_ops)); - kic_inst->ant_ops_tuple.priv = NULL; - mutex_unlock(&kic_inst->ant_ops_tuple.ops_mutex); -} -EXPORT_SYMBOL(slsi_kic_ant_ops_unregister); -#endif diff --git a/drivers/misc/samsung/kic/slsi_kic_sap_bt.c b/drivers/misc/samsung/kic/slsi_kic_sap_bt.c deleted file mode 100755 index ebc48f72317d..000000000000 --- a/drivers/misc/samsung/kic/slsi_kic_sap_bt.c +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "slsi_kic_internal.h" - -int slsi_kic_bt_ops_register(void *priv, struct slsi_kic_bt_ops *bt_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - if (!kic_inst) - return -EFAULT; - - mutex_lock(&kic_inst->bt_ops_tuple.ops_mutex); - memcpy(&kic_inst->bt_ops_tuple.bt_ops, bt_ops, sizeof(struct slsi_kic_bt_ops)); - kic_inst->bt_ops_tuple.priv = priv; - mutex_unlock(&kic_inst->bt_ops_tuple.ops_mutex); - return 0; -} -EXPORT_SYMBOL(slsi_kic_bt_ops_register); - -void slsi_kic_bt_ops_unregister(struct slsi_kic_bt_ops *bt_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - OS_UNUSED_PARAMETER(bt_ops); - - if (!kic_inst) - return; - - mutex_lock(&kic_inst->bt_ops_tuple.ops_mutex); - memset(&kic_inst->bt_ops_tuple.bt_ops, 0, sizeof(struct slsi_kic_bt_ops)); - kic_inst->bt_ops_tuple.priv = NULL; - mutex_unlock(&kic_inst->bt_ops_tuple.ops_mutex); -} -EXPORT_SYMBOL(slsi_kic_bt_ops_unregister); diff --git a/drivers/misc/samsung/kic/slsi_kic_sap_cm.c b/drivers/misc/samsung/kic/slsi_kic_sap_cm.c deleted file mode 100755 index 666c1041b96e..000000000000 --- a/drivers/misc/samsung/kic/slsi_kic_sap_cm.c +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "slsi_kic_internal.h" - -int slsi_kic_cm_ops_register(void *priv, struct slsi_kic_cm_ops *cm_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - if (!kic_inst) - return -EFAULT; - - mutex_lock(&kic_inst->cm_ops_tuple.ops_mutex); - memcpy(&kic_inst->cm_ops_tuple.cm_ops, cm_ops, sizeof(struct slsi_kic_cm_ops)); - kic_inst->cm_ops_tuple.priv = priv; - mutex_unlock(&kic_inst->cm_ops_tuple.ops_mutex); - return 0; -} -EXPORT_SYMBOL(slsi_kic_cm_ops_register); - -void slsi_kic_cm_ops_unregister(struct slsi_kic_cm_ops *cm_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - OS_UNUSED_PARAMETER(cm_ops); - - if (!kic_inst) - return; - - mutex_lock(&kic_inst->cm_ops_tuple.ops_mutex); - memset(&kic_inst->cm_ops_tuple.cm_ops, 0, sizeof(struct slsi_kic_cm_ops)); - kic_inst->cm_ops_tuple.priv = NULL; - mutex_unlock(&kic_inst->cm_ops_tuple.ops_mutex); -} -EXPORT_SYMBOL(slsi_kic_cm_ops_unregister); diff --git a/drivers/misc/samsung/kic/slsi_kic_sap_wifi.c b/drivers/misc/samsung/kic/slsi_kic_sap_wifi.c deleted file mode 100755 index 869f27d9fb88..000000000000 --- a/drivers/misc/samsung/kic/slsi_kic_sap_wifi.c +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "slsi_kic_internal.h" - -int slsi_kic_wifi_ops_register(void *priv, struct slsi_kic_wifi_ops *wifi_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - if (!kic_inst) - return -EFAULT; - - mutex_lock(&kic_inst->wifi_ops_tuple.ops_mutex); - memcpy(&kic_inst->wifi_ops_tuple.wifi_ops, wifi_ops, sizeof(struct slsi_kic_wifi_ops)); - kic_inst->wifi_ops_tuple.priv = priv; - mutex_unlock(&kic_inst->wifi_ops_tuple.ops_mutex); - return 0; -} -EXPORT_SYMBOL(slsi_kic_wifi_ops_register); - -void slsi_kic_wifi_ops_unregister(struct slsi_kic_wifi_ops *wifi_ops) -{ - struct slsi_kic_pdata *kic_inst = slsi_kic_core_get_context(); - - OS_UNUSED_PARAMETER(wifi_ops); - - if (!kic_inst) - return; - - mutex_lock(&kic_inst->wifi_ops_tuple.ops_mutex); - memset(&kic_inst->wifi_ops_tuple.wifi_ops, 0, sizeof(struct slsi_kic_wifi_ops)); - kic_inst->wifi_ops_tuple.priv = NULL; - mutex_unlock(&kic_inst->wifi_ops_tuple.ops_mutex); -} -EXPORT_SYMBOL(slsi_kic_wifi_ops_unregister); diff --git a/drivers/misc/samsung/scsc/Kconfig b/drivers/misc/samsung/scsc/Kconfig deleted file mode 100644 index 260c60046074..000000000000 --- a/drivers/misc/samsung/scsc/Kconfig +++ /dev/null @@ -1,189 +0,0 @@ -config SCSC_CORE_CM - tristate "Samsung SCSC Maxwell driver Core Module" - depends on SCSC_CORE - -config SCSC_CORE - tristate "Samsung SCSC Maxwell driver" - select SCSC_CORE_CM - -config SCSC_WLBT_CONFIG_PLATFORM - string "SCSC WLBT PLATFORM" - default "" - ---help--- - Select the platform, e.g. lassen_smdk - -config SCSC_CORE_FW_LOCATION - string "SCSC FW location" - default "/system/etc/wifi" - ---help--- - Select the FW location, when CONFIG_SCSC_CORE_FW_LOCATION_AUTO=n - -config SCSC_CORE_FW_LOCATION_AUTO - string "SCSC FW location auto select" - default y - ---help--- - Select the FW location (Android N/O) automatically - -config SCSC_CORE_TOOL_LOCATION - string "SCSC tool location" - default "/system/bin" - ---help--- - Select the moredump tool location, when CONFIG_SCSC_CORE_FW_LOCATION_AUTO=n - -config SCSC_PCIE - tristate "Samsung SCSC MIF PCIE implementation" - depends on SCSC_CORE - depends on PCI - -config SCSC_MXLOGGER - bool "Samsung SCSC MXLOGGER" - depends on SCSC_CORE - default y - ---help--- - MXLOGGER provides FW level logging in DRAM - -config SCSC_SMAPPER - bool "Samsung SCSC WLAN Smapper support" - default y - depends on SCSC_CORE - ---help--- - SMAPPER provides direct access to Linux SKBs - -config SCSC_WLBTD - bool "Samsung SCSC Daemon support for Android O" - depends on SCSC_CORE - default n - ---help--- - Uses generic netlink messages to communicate events to userspace daemon which takes necessary actions e.g. taking moredump - -config SCSC_WRITE_INFO_FILE_WLBTD - bool "SCSC flag to decide whether to write file via wlbtd or not" - depends on SCSC_WLBTD - default n - -config SCSC_QOS - bool "Samsung SCSC kernel PM QoS support" - default y - depends on SCSC_CORE - ---help--- - SCSC_QOS provides support to configure kernel PM QoS to register configuration as per performance expectations - -config SCSC_PLATFORM - tristate "Samsung SCSC MIF Platform driver implementation" - depends on SCSC_CORE - -config SCSC_CM_MX_CLIENT_TEST - tristate "Samsung SCSC Test Client" - depends on SCSC_CORE - -config SCSC_MX_ALWAYS_ON - tristate "Samsung SCSC MX140 always booted" - depends on SCSC_CM_MX_CLIENT_TEST - -config SCSC_CLK20MHZ - tristate "Samsung SCSC USB 20MHz Clock" - depends on SCSC_CORE - -config SCSC_CLK20MHZ_TEST - tristate "Samsung SCSC USB 20MHz Clock Test" - depends on SCSC_CLK20MHZ - -config SCSC_FM - tristate "Samsung SCSC MX250 enables LDOs used for FM" - depends on SCSC_CORE - -config SCSC_FM_TEST - tristate "Samsung SCSC MX250 Test for enabling LDOs used for FM" - depends on SCSC_FM - -config SCSC_MMAP - tristate "Samsung SCSC MMAP/GDB User space interface" - depends on SCSC_CORE - -config SCSC_DBG_SAMPLER - tristate "Samsung SCSC Debug Sampler Service" - depends on SCSC_CORE - -config SCSC_DEBUG - tristate "Samsung SCSC Logging" - depends on SCSC_CORE && DEBUG_FS - default n - -config SCSC_DEBUG_COMPATIBILITY - bool "Samsung SCSC Logging mode" - default y - -config SCSC_LOGRING - tristate "Samsung SCSC Kernel Logging" - default y - ---help--- - SCSC Drivers logging mechanism - -config SCSC_STATIC_RING - tristate "Samsung SCSC Logging use static ring" - depends on SCSC_LOGRING - default y - -config SCSC_STATIC_RING_SIZE - int "Size of the static ring" - depends on SCSC_STATIC_RING - default "1048576" - range 1024 16777216 - -config SCSC_CHV_SUPPORT - bool "Samsung CHV f/w support" - depends on SCSC_CORE - default n - -config SCSC_GPR4_CON_DEBUG - bool "GPR4 PIO muxes switching to the Maxwell Subsystem" - depends on SCSC_PLATFORM - default n - -config SCSC_BUILD_TYPE - string "Type of Kernel Build" - ---help--- - Type of Kernel Build: User, User Debug, Engineering - -config SCSC_WIFILOGGER - tristate "Samsung SCSC Android Wi-Fi Logger" - depends on SCSC_CORE - default n - -config SCSC_WIFILOGGER_DEBUGFS - bool "Samsung SCSC Android Wi-Fi Logger DebugFS" - depends on SCSC_WIFILOGGER && DEBUG_FS - default y - -config SCSC_WIFILOGGER_TEST - bool "Samsung SCSC Android Wi-Fi Logger Test Harness" - depends on SCSC_WIFILOGGER && SCSC_WIFILOGGER_DEBUGFS - default n - -config SCSC_LOG_COLLECTION - bool "Samsung SCSC Log Collection" - depends on SCSC_CORE - default y - ---help--- - Enable LOG collection to collect Chunks (host and FW) and generate a SBL file - -config SCSC_COMMON_HCF - bool "Enable Common HCF loader" - depends on SCSC_CORE - default n - ---help--- - Enable Common HCF loader - -config SCSC_WLBT_AUTORECOVERY_PERMANENT_DISABLE - bool "Permanently disable WLBT autorecovery, ignroring module parameter" - depends on SCSC_CORE - default n - ---help--- - Override module parameter, and disable recovery - -config SCSC_MX450_GDB_SUPPORT - bool "Enable GDB Channels for MX450" - depends on SCSC_CORE - default n - ---help--- - Enable GDB Channels for MX450 diff --git a/drivers/misc/samsung/scsc/Makefile b/drivers/misc/samsung/scsc/Makefile deleted file mode 100644 index 6bf1424f1e99..000000000000 --- a/drivers/misc/samsung/scsc/Makefile +++ /dev/null @@ -1,164 +0,0 @@ -############################################################################# -# -# Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -# -############################################################################# - -# Needed since this subdir is symlinked in the main Kernel tree -# without this our samsung subdir is NOT cleaned. -clean-files := *.o *.ko - -ifneq ($(CONFIG_SCSC_CORE),n) - -ccflags-y += -Iinclude/scsc -ccflags-y += $(CONFIG_SAMSUNG_MAXWELL_EXTRA) - -obj-$(CONFIG_SCSC_LOGRING) += scsc_logring.o -scsc_logring-$(CONFIG_SCSC_LOGRING) += scsc_logring_main.o scsc_logring_ring.o scsc_logring_debugfs.o - -obj-$(CONFIG_SCSC_LOG_COLLECTION) += scsc_log_collection.o -scsc_log_collection-y += scsc_log_collector.o scsc_log_collector_proc.o scsc_log_collector_mmap.o -## -## The following cumbersome ifeq/else is the only way to make -## this CONFIG_SCSC_PRINTK propagate correctly in any scenario (y,m,n) -## Otherwise using ONLY the else branch when CONFIG_SCSC_DEBUG evaluates -## to m ==>> ccflags-m does NOT work correctly in every build scenario: -## - kernel debug modules : builtin with scsc_logring support -## - kernel nodebug modules : builtins without scsc_logring support -## - kernel debug|nodebug nomodules : no builtin / no scsclogring -## -ifeq ($(CONFIG_SCSC_DEBUG), m) -ccflags-y += -DCONFIG_SCSC_PRINTK -else -ccflags-$(CONFIG_SCSC_LOGRING) += -DCONFIG_SCSC_PRINTK -endif - -ifneq ($(CONFIG_SCSC_DEBUG),n) -ccflags-$(CONFIG_SCSC_STATIC_RING) += -DCONFIG_SCSC_STATIC_RING_SIZE=$(CONFIG_SCSC_STATIC_RING_SIZE) -endif - -obj-$(CONFIG_SCSC_WIFILOGGER) += scsc_wifilogger.o -scsc_wifilogger-y += scsc_wifilogger_api.o \ - scsc_wifilogger_internal.o \ - scsc_wifilogger_core.o \ - scsc_wifilogger_module.o \ - scsc_wifilogger_ring_connectivity.o \ - scsc_wifilogger_ring_wakelock.o \ - scsc_wifilogger_ring_pktfate.o - -scsc_wifilogger-$(CONFIG_SCSC_WIFILOGGER_DEBUGFS) += scsc_wifilogger_debugfs.o -scsc_wifilogger-$(CONFIG_SCSC_WIFILOGGER_TEST) += scsc_wifilogger_ring_test.o - -# GDB channels for MoreDump -ccflags-$(CONFIG_SCSC_MX450_GDB_SUPPORT) += -DCONFIG_SCSC_MX450_GDB_SUPPORT - -# PCI-E MIF -obj-$(CONFIG_SCSC_PCIE) += scsc_pcie_mif.o -scsc_pcie_mif-y += pcie_mif_module.o pcie_mif.o pcie_proc.o pcie_mbox.o pcie_mbox_intgen.o - -obj-$(CONFIG_SCSC_PLATFORM) += scsc_platform_mif.o - -scsc_platform_mif-$(CONFIG_SCSC_PLATFORM) += \ - platform_mif_module.o - -ifeq ($(CONFIG_SOC_EXYNOS9610),y) - scsc_platform_mif-$(CONFIG_SCSC_PLATFORM) += platform_mif_9610.o -endif -ifeq ($(CONFIG_SOC_EXYNOS9630),y) - scsc_platform_mif-$(CONFIG_SCSC_PLATFORM) += platform_mif_9630.o -endif -ifeq ($(CONFIG_SOC_EXYNOS3830),y) - scsc_platform_mif-$(CONFIG_SCSC_PLATFORM) += platform_mif_3830.o -endif -ifeq ($(CONFIG_SOC_EXYNOS7570),y) - scsc_platform_mif-$(CONFIG_SCSC_PLATFORM) += platform_mif.o -endif -ifeq ($(CONFIG_SOC_EXYNOS7872),y) - scsc_platform_mif-$(CONFIG_SCSC_PLATFORM) += platform_mif.o -endif -ifeq ($(CONFIG_SOC_EXYNOS7885),y) - scsc_platform_mif-$(CONFIG_SCSC_PLATFORM) += platform_mif.o -endif - -#core_module for static functions and registration client module (all the service driver modules -wlan, bt,...-) -#core for instance -obj-$(CONFIG_SCSC_CORE_CM) += scsc_mx.o -scsc_mx-y += \ - mxlog_transport.o \ - fw_panic_record.o \ - panicmon.o \ - suspendmon.o \ - mxlog.o \ - mxproc.o \ - scsc_service.o \ - scsc_mx_module.o \ - scsc_mx_impl.o \ - mxman.o \ - miframman.o \ - mifmboxman.o \ - mifproc.o \ - mifintrbit.o \ - fwhdr.o \ - fwimage.o \ - cpacket_buffer.o \ - mifstream.o \ - mxmgmt_transport.o \ - gdb_transport.o \ - scsc_lerna.o \ - mxsyserr.o \ - mxfwconfig.o \ - mx140_file.o - -scsc_mx-$(CONFIG_SCSC_MXLOGGER) += mxlogger.o - -scsc_mx-$(CONFIG_SCSC_SMAPPER) += mifsmapper.o - -scsc_mx-$(CONFIG_SCSC_WLBTD) += scsc_wlbtd.o - -scsc_mx-$(CONFIG_SCSC_QOS) += mifqos.o - -ifneq ($(CONFIG_SCSC_CM_MX_CLIENT_TEST),n) -obj-$(CONFIG_SCSC_CM_MX_CLIENT_TEST) += mx_client_test.o -mx_client_test-y += client_test.o -endif - -ifneq ($(CONFIG_SCSC_MMAP),n) -obj-$(CONFIG_SCSC_MMAP) += scsc_mmap.o -scsc_mmap-y += mx_mmap.o -endif - -ifneq ($(CONFIG_SCSC_CLK20MHZ),n) -obj-$(CONFIG_SCSC_CLK20MHZ) += scsc_mx140_clk.o -scsc_mx140_clk-y += mx140_clk.o -ifeq ($(CONFIG_SCSC_CLK20MHZ_TEST),y) -scsc_mx140_clk-y += mx140_clk_test.o -endif -endif - -ifneq ($(CONFIG_SCSC_FM),n) -obj-$(CONFIG_SCSC_FM) += scsc_mx250_fm.o -scsc_mx250_fm-y += mx250_fm.o -ifeq ($(CONFIG_SCSC_FM_TEST),y) -scsc_mx250_fm-y += mx250_fm_test.o -endif -endif - -obj-$(CONFIG_SCSC_DBG_SAMPLER) += scsc_dbg_sampler.o -scsc_dbg_sampler-y += mx_dbg_sampler.o - -endif - -# The below section is only for DTE purpose. It is controlled by the flag SCSC_DTE_BUILD which is set only by the -# DTE top level Makefile. Hence, no risk. -# In the below include dir the KERNEL_DIR comes from the DTE top level makefile. -ifeq ($(SCSC_DTE_BUILD),y) -obj-m := scsc_mx.o -obj-m += mx_client_test.o -mx_client_test-y += client_test.o - -ccflags-y += -I$(KERNEL_DIR)/include/scsc/ -ccflags-y += -I$(KERNEL_DIR)/include -ccflags-y += -I$(KERNEL_DIR)/drivers/misc/samsung/scsc -ccflags-y += -I$(KERNEL_DIR)/drivers/net/wireless/scsc - -endif diff --git a/drivers/misc/samsung/scsc/client_test.c b/drivers/misc/samsung/scsc/client_test.c deleted file mode 100755 index a9ef8bd8755e..000000000000 --- a/drivers/misc/samsung/scsc/client_test.c +++ /dev/null @@ -1,434 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -struct scsc_mx_test { - /* scsc_service_client has to be the first */ - struct scsc_service_client test_service_client; - struct scsc_service *primary_service; - struct scsc_service *secondary_service; - struct scsc_mx *mx; - bool started; -}; - -static struct scsc_mx_test *test; - -/* First service to start */ -static int service_id = SCSC_SERVICE_ID_NULL; -module_param(service_id, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(service_id, "ID of service to start, Default 0:NULL, 1:WLAN, 2:BT, 3:ANT, 5:ECHO"); - -/* Second service to start if != -1 */ -static int service_id_2 = -1; -module_param(service_id_2, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(service_id_2, "ID of optional second service to start: Default -1:None, 0:NULL, 1:WLAN, 2:BT, 3:ANT, 5:ECHO"); - -#ifdef CONFIG_SCSC_MX_ALWAYS_ON -static int auto_start = 2; -#else -static int auto_start; -#endif -module_param(auto_start, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(auto_start, "Start service automatically: 0: disabled, 1: Enabled, 2: Deferred"); - -/* Delay after probe before starting mx140 when auto_start=2 */ -#define SCSC_MX_BOOT_DELAY_MS 30000 - -static DEFINE_MUTEX(ss_lock); - -/* char device entry declarations */ -static dev_t client_test_dev_t; -static struct class *client_test_class; -static struct cdev *client_test_cdev; - -static u8 test_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void) client; - SCSC_TAG_DEBUG(MXMAN_TEST, "OK\n"); - return err->level; -} - - -static bool test_stop_on_failure(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void) client; - (void) err; - SCSC_TAG_DEBUG(MXMAN_TEST, "OK\n"); - return false; -} - -static void test_failure_reset(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code) -{ - (void)client; - (void)level; - (void)scsc_syserr_code; - SCSC_TAG_ERR(MXMAN_TEST, "OK\n"); -} - - -static void stop_close_services(void) -{ - int r; - - mutex_lock(&ss_lock); - - if (!test->started) { - pr_info("mx140: already stopped\n"); - goto done; - } - - if (test->primary_service) { - r = scsc_mx_service_stop(test->primary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_stop(primary_service) failed err: %d\n", r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_stop(primary_service) OK\n"); - r = scsc_mx_service_close(test->primary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_close(%d) failed err: %d\n", service_id, r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_close(%d) OK\n", service_id); - test->primary_service = NULL; - } - - if (test->secondary_service) { - r = scsc_mx_service_stop(test->secondary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_stop(secondary_service) failed err: %d\n", r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_stop(secondary_service) OK\n"); - r = scsc_mx_service_close(test->secondary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_close(%d) failed err: %d\n", service_id_2, r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_close(%d) OK\n", service_id_2); - test->secondary_service = NULL; - } - test->started = false; -done: - mutex_unlock(&ss_lock); -} - -static bool open_start_services(struct scsc_mx *mx) -{ - struct scsc_service *primary_service; - struct scsc_service *secondary_service; - int r; - bool ok; - - mutex_lock(&ss_lock); - - if (test->started) { - pr_info("mx140: already started\n"); - ok = true; - goto done; - } - - primary_service = scsc_mx_service_open(mx, service_id, &test->test_service_client, &r); - if (!primary_service) { - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_open for primary_service failed %d\n", r); - ok = false; - goto done; - } - - r = scsc_mx_service_start(primary_service, 0); - if (r) { - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_start for primary_service failed\n"); - r = scsc_mx_service_close(primary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_close for primary_service %d failed\n", r); - ok = false; - goto done; - } - - test->primary_service = primary_service; - - if (service_id_2 != -1) { - secondary_service = scsc_mx_service_open(mx, service_id_2, &test->test_service_client, &r); - if (!secondary_service) { - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_open for secondary_service failed %d\n", r); - r = scsc_mx_service_stop(test->primary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_stop(%d) failed err: %d\n", service_id, r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_stop(%d) OK\n", service_id); - r = scsc_mx_service_close(test->primary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_close(%d) failed err: %d\n", service_id, r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_close(%d) OK\n", service_id); - ok = false; - goto done; - } - r = scsc_mx_service_start(secondary_service, 0); - if (r) { - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_start for secondary_service failed\n"); - r = scsc_mx_service_close(secondary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_close(%d) failed err: %d\n", service_id, r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_close(%d) OK\n", service_id); - - r = scsc_mx_service_stop(test->primary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_stop(%d) failed err: %d\n", service_id, r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_stop(%d) OK\n", service_id); - r = scsc_mx_service_close(test->primary_service); - if (r) - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_service_close(%d) failed err: %d\n", service_id, r); - else - SCSC_TAG_DEBUG(MXMAN_TEST, "scsc_mx_service_close(%d) OK\n", service_id); - ok = false; - goto done; - } - test->secondary_service = secondary_service; - } - test->started = true; - ok = true; -done: - mutex_unlock(&ss_lock); - return ok; -} - -static void delay_start_func(struct work_struct *work) -{ - (void)work; - - pr_info("mx140: Start wlbt null service\n"); - - if (!test->mx) - return; - - if (!open_start_services(test->mx)) - pr_err("mx140: Error starting delayed service\n"); -} - -DECLARE_DELAYED_WORK(delay_start, delay_start_func); - -/* Start the null service after a delay */ -static void delay_open_start_services(void) -{ - schedule_delayed_work(&delay_start, msecs_to_jiffies(SCSC_MX_BOOT_DELAY_MS)); -} - -/* Start service(s) and leave running until module unload */ -void client_module_probe(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - /* Avoid unused error */ - (void)module_client; - - SCSC_TAG_ERR(MXMAN_TEST, "mx140:\n"); - - test = kzalloc(sizeof(*test), GFP_KERNEL); - if (!test) - return; - - test->test_service_client.failure_notification = test_failure_notification; - test->test_service_client.stop_on_failure_v2 = test_stop_on_failure; - test->test_service_client.failure_reset_v2 = test_failure_reset; - test->mx = mx; - - switch (auto_start) { - case 1: - if (!open_start_services(test->mx)) { - SCSC_TAG_ERR(MXMAN_TEST, "Error starting service/s\n"); - kfree(test); - return; - } - break; - case 2: - pr_info("mx140: delayed auto-start\n"); - delay_open_start_services(); - break; - default: - break; - } - - SCSC_TAG_ERR(MXMAN_TEST, "OK\n"); -} - -void client_module_remove(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - /* Avoid unused error */ - (void)module_client; - - pr_info("mx140: %s\n", __func__); - - if (!test) - return; - if (test->mx != mx) { - SCSC_TAG_ERR(MXMAN_TEST, "test->mx != mx\n"); - return; - } - - /* Cancel any delayed start attempt */ - cancel_delayed_work_sync(&delay_start); - - stop_close_services(); - - /* de-allocate test structure */ - kfree(test); - SCSC_TAG_DEBUG(MXMAN_TEST, "OK\n"); -} - - -/* Test client driver registration */ -struct scsc_mx_module_client client_test_driver = { - .name = "MX client test driver", - .probe = client_module_probe, - .remove = client_module_remove, -}; - - -static int client_test_dev_open(struct inode *inode, struct file *file) -{ - SCSC_TAG_ERR(MXMAN_TEST, "open client test\n"); - return 0; -} - -static ssize_t client_test_dev_write(struct file *file, const char *data, size_t len, loff_t *offset) -{ - unsigned long count; - char str[2]; /* One value and carry return */ - long int val = 0; - bool ok = true; - - if (len > 2) { - SCSC_TAG_ERR(MXMAN_TEST, "Incorrect value len %zd\n", len); - goto error; - } - - count = copy_from_user(str, data, len); - - str[1] = 0; - - if (kstrtol(str, 10, &val)) { - SCSC_TAG_ERR(MXMAN_TEST, "Invalid value\n"); - goto error; - } - - if (test) { - if (val) { - SCSC_TAG_INFO(MXMAN_TEST, "Start services\n"); - ok = open_start_services(test->mx); - } else { - SCSC_TAG_INFO(MXMAN_TEST, "Stop services\n"); - stop_close_services(); - } - } else { - SCSC_TAG_ERR(MXMAN_TEST, "Test not created\n"); - goto error; - } -error: - SCSC_TAG_ERR(MXMAN_TEST, "%s\n", ok ? "OK" : "FAIL"); - return ok ? len : -EIO; -} - -static ssize_t client_test_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) -{ - return length; -} - -static int client_test_dev_release(struct inode *inode, struct file *file) -{ - SCSC_TAG_DEBUG(MXMAN_TEST, "close client test\n"); - return 0; -} - -static const struct file_operations client_test_dev_fops = { - .owner = THIS_MODULE, - .open = client_test_dev_open, - .read = client_test_dev_read, - .write = client_test_dev_write, - .release = client_test_dev_release, -}; - -static int __init scsc_client_test_module_init(void) -{ - int r; - - SCSC_TAG_DEBUG(MXMAN_TEST, "mx140:\n"); - - r = scsc_mx_module_register_client_module(&client_test_driver); - if (r) { - SCSC_TAG_ERR(MXMAN_TEST, "scsc_mx_module_register_client_module failed: r=%d\n", r); - return r; - } - - r = alloc_chrdev_region(&client_test_dev_t, 0, 1, "wlbt-null-service"); - if (r < 0) { - SCSC_TAG_ERR(MXMAN_TEST, "failed to alloc chrdev region\n"); - goto fail_alloc_chrdev_region; - } - - client_test_cdev = cdev_alloc(); - if (!client_test_cdev) { - r = -ENOMEM; - SCSC_TAG_ERR(MXMAN_TEST, "failed to alloc cdev\n"); - goto fail_alloc_cdev; - } - - cdev_init(client_test_cdev, &client_test_dev_fops); - r = cdev_add(client_test_cdev, client_test_dev_t, 1); - if (r < 0) { - SCSC_TAG_ERR(MXMAN_TEST, "failed to add cdev\n"); - goto fail_add_cdev; - } - - client_test_class = class_create(THIS_MODULE, "sample"); - if (!client_test_class) { - r = -EEXIST; - SCSC_TAG_ERR(MXMAN_TEST, "failed to create class\n"); - goto fail_create_class; - } - - if (!device_create(client_test_class, NULL, client_test_dev_t, NULL, "mx_client_test_%d", MINOR(client_test_dev_t))) { - r = -EINVAL; - SCSC_TAG_ERR(MXMAN_TEST, "failed to create device\n"); - goto fail_create_device; - } - - return 0; -fail_create_device: - class_destroy(client_test_class); -fail_create_class: - cdev_del(client_test_cdev); -fail_add_cdev: -fail_alloc_cdev: - unregister_chrdev_region(client_test_dev_t, 1); -fail_alloc_chrdev_region: - return r; -} - -static void __exit scsc_client_test_module_exit(void) -{ - SCSC_TAG_DEBUG(MXMAN_TEST, "mx140:\n"); - scsc_mx_module_unregister_client_module(&client_test_driver); - SCSC_TAG_DEBUG(MXMAN_TEST, "exit\n"); - - device_destroy(client_test_class, client_test_dev_t); - class_destroy(client_test_class); - cdev_del(client_test_cdev); - unregister_chrdev_region(client_test_dev_t, 1); -} - -late_initcall(scsc_client_test_module_init); -module_exit(scsc_client_test_module_exit); - -MODULE_DESCRIPTION("mx140 Client Test Driver"); -MODULE_AUTHOR("SCSC"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/samsung/scsc/cpacket_buffer.c b/drivers/misc/samsung/scsc/cpacket_buffer.c deleted file mode 100644 index ba555c8b362b..000000000000 --- a/drivers/misc/samsung/scsc/cpacket_buffer.c +++ /dev/null @@ -1,373 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Software Mailbox Emulation shared data definitions. -* -* Ref: SC-506707-DD - Structure version 2 -* -****************************************************************************/ -/** - * Circular buffer backed packet stream (Implementation) - * - * To allow easy distinction between full and empty buffers, there - * is one slot reserved in the available space. This means that the following - * conditions can be used to easily test the buffer's status without tracking - * the used size explicitly: - * - read_index == write_index : Buffer is empty - * - write_index + 1 == read_index : Buffer is full - * Otherwise if read_index == write_index then the buffer could be either - * empty or full. - */ -/* Implements */ -#include "cpacket_buffer.h" - -/* Uses */ -#include -#include -#include "miframman.h" - - -/** - * Advances the read/write index by the given amount, wrapping around if this - * exceeds the buffer length. - */ -static inline void cpacketbuffer_advance_index(uint32_t *idx, uint32_t amount, uint32_t buffer_size) -{ - *idx = (*idx + amount) % buffer_size; -} - -/** - * Converts a buffer address to a read/write index. - * - * The address must be at the start of a packet. - */ -static inline uint32_t cpacketbuffer_address_to_index(struct cpacketbuffer *buffer, const uint8_t *address) -{ - ptrdiff_t offset = address - (uint8_t *)buffer->buffer; - - return (offset / buffer->packet_size) % buffer->num_packets; -} - -/** - * Converts a buffer read/write index to an address. - */ -static inline uint8_t *cpacketbuffer_index_to_address(struct cpacketbuffer *buffer, uint32_t *idx) -{ - return (uint8_t *)buffer->buffer + (*idx % buffer->num_packets) * buffer->packet_size; -} - -/** Returns the current read index of the buffer */ -static inline uint32_t cpacketbuffer_read_index(const struct cpacketbuffer *buffer) -{ - return *buffer->read_index; -} - -/** Returns the current write index of the buffer */ -static inline uint32_t cpacketbuffer_write_index(const struct cpacketbuffer *buffer) -{ - return *buffer->write_index; -} - -/** Writes a set of whole packets to the buffer */ -static bool cpacketbuffer_write_block(struct cpacketbuffer *buffer, const void *buf, uint32_t num_bytes) -{ - uint32_t num_packets = (num_bytes + buffer->packet_size - 1) / buffer->packet_size; - const uint8_t *source_data; - uint32_t start_write_index; - uint32_t end_write_index; - - if (num_packets > cpacketbuffer_free_space(buffer)) - /* Not enough free packets to write this block */ - return false; - - source_data = (const uint8_t *)buf; - start_write_index = cpacketbuffer_write_index(buffer); - end_write_index = start_write_index; - cpacketbuffer_advance_index(&end_write_index, num_packets - 1, buffer->num_packets); - - if (end_write_index < start_write_index) { - /* Writes wrap around the buffer, split the write in two */ - uint32_t initial_write_size = (buffer->num_packets - start_write_index) * buffer->packet_size; - - memcpy(cpacketbuffer_index_to_address(buffer, buffer->write_index), source_data, initial_write_size); - memcpy(buffer->buffer, source_data + initial_write_size, num_bytes - initial_write_size); - } else - memcpy(cpacketbuffer_index_to_address(buffer, buffer->write_index), source_data, num_bytes); - - /* CPU memory barrier */ - wmb(); - cpacketbuffer_advance_index(buffer->write_index, num_packets, buffer->num_packets); - - return true; -} - -/** Log buffer configuration at DEBUG level */ -static void mxcbufconf_print(const struct mxcbufconf *buf_conf) -{ - SCSC_TAG_DBG4(CPKTBUFF, "mxcbufconf\n\tbuffer_loc: 0x%x\n\tnum_packets: %d\n\tpacket_size: %d\n\treadix: 0x%x\n\twriteix: 0x%x\n", - buf_conf->buffer_loc, - buf_conf->num_packets, - buf_conf->packet_size, - buf_conf->read_index_loc, - buf_conf->write_index_loc - ); -} - -/** Externally visible functions */ - -int cpacketbuffer_init(struct cpacketbuffer *buffer, uint32_t num_packets, uint32_t packet_size, struct scsc_mx *mx) -{ - struct miframman *miframman; - uint32_t *ridx; - uint32_t *widx; - void *mem; - - buffer->mx = mx; - - miframman = scsc_mx_get_ramman(mx); - mem = miframman_alloc(miframman, num_packets * packet_size, 4, MIFRAMMAN_OWNER_COMMON); - if (!mem) - return -ENOMEM; - - ridx = miframman_alloc(miframman, sizeof(uint32_t), 4, MIFRAMMAN_OWNER_COMMON); - if (!ridx) { - miframman_free(miframman, mem); - return -ENOMEM; - } - - widx = miframman_alloc(miframman, sizeof(uint32_t), 4, MIFRAMMAN_OWNER_COMMON); - if (!widx) { - miframman_free(miframman, ridx); - miframman_free(miframman, mem); - return -ENOMEM; - } - - buffer->buffer = mem; - buffer->num_packets = num_packets; - buffer->packet_size = packet_size; - buffer->read_index = ridx; - buffer->write_index = widx; - - *buffer->read_index = 0; - *buffer->write_index = 0; - return 0; -} - -void cpacketbuffer_release(struct cpacketbuffer *buffer) -{ - struct miframman *miframman; - - miframman = scsc_mx_get_ramman(buffer->mx); - - miframman_free(miframman, buffer->read_index); - miframman_free(miframman, buffer->write_index); - miframman_free(miframman, buffer->buffer); -} - -bool cpacketbuffer_write(struct cpacketbuffer *buffer, const void *buf, uint32_t num_bytes) -{ - uint32_t start_write_index; - - if (buf == NULL || num_bytes == 0) - return false; - - SCSC_TAG_DBG4(CPKTBUFF, "Before: *buffer->read_index=0x%x *buffer->write_index=0x%x\n", - *buffer->read_index, *buffer->write_index); - - start_write_index = cpacketbuffer_write_index(buffer); - if (!cpacketbuffer_write_block(buffer, buf, num_bytes)) - return false; - - /* CPU memory barrier */ - wmb(); - - SCSC_TAG_DBG4(CPKTBUFF, "After: *buffer->read_index=0x%x *buffer->write_index=0x%x\n", - *buffer->read_index, *buffer->write_index); - - return true; -} - -bool cpacketbuffer_write_gather(struct cpacketbuffer *buffer, const void **bufs, uint32_t *num_bytes, uint32_t num_bufs) -{ - uint32_t start_write_index; - uint32_t i; - - if (bufs == NULL || num_bytes == 0 || num_bufs == 0) - return false; - - start_write_index = cpacketbuffer_write_index(buffer); - for (i = 0; i < num_bufs; ++i) { - /* Write all the whole packets from this buffer */ - uint32_t partial_packet_len = num_bytes[i] % buffer->packet_size; - uint32_t whole_packet_len = num_bytes[i] - partial_packet_len; - - if (whole_packet_len > 0 && - !cpacketbuffer_write_block(buffer, bufs[i], whole_packet_len)) - return false; - - if (partial_packet_len != 0) { - /* Partial packet present - write this and enough from the next data block(s) to fill this packet - * before continuing */ - uint32_t needed_bytes; - uint8_t *write_ptr = cpacketbuffer_index_to_address(buffer, buffer->write_index); - - memcpy(write_ptr, (const uint8_t *)bufs[i] + whole_packet_len, partial_packet_len); - write_ptr += partial_packet_len; - needed_bytes = buffer->packet_size - partial_packet_len; - while (i + 1 < num_bufs && needed_bytes > 0) { - uint32_t num_bytes_to_take = num_bytes[i + 1] >= needed_bytes ? needed_bytes : num_bytes[i + 1]; - - memcpy(write_ptr, bufs[i + 1], num_bytes_to_take); - bufs[i + 1] = (const uint8_t *)bufs[i + 1] + num_bytes_to_take; - num_bytes[i + 1] -= num_bytes_to_take; - write_ptr += num_bytes_to_take; - needed_bytes -= num_bytes_to_take; - - if (num_bytes[i + 1] == 0) - /* This buffer has been consumed entirely, move to the next */ - ++i; - } - - /* CPU memory barrier */ - wmb(); - cpacketbuffer_advance_index(buffer->write_index, 1, buffer->num_packets); - } - } - - /* CPU memory barrier */ - wmb(); - - return true; -} - -uint32_t cpacketbuffer_read(struct cpacketbuffer *buffer, void *buf, uint32_t num_bytes) -{ - uint8_t *read_start; - uint32_t num_packets; - uint32_t num_available_packets; - - if (buf == NULL || cpacketbuffer_is_empty(buffer)) - return 0; - - /* Work out where we're reading from */ - read_start = cpacketbuffer_index_to_address(buffer, buffer->read_index); - num_packets = num_bytes / buffer->packet_size; - if (num_bytes % buffer->packet_size != 0) - /* Partial data packet read requested, this means we remove the whole thing */ - ++num_packets; - - /* Ensure we have enough actual data to satisfy the read request, otherwise - * truncate the read request to the amount of data available. */ - num_available_packets = buffer->num_packets - (cpacketbuffer_free_space(buffer) + 1); - if (num_packets > num_available_packets) { - num_packets = num_available_packets; - num_bytes = num_packets * buffer->packet_size; - } - - if (cpacketbuffer_read_index(buffer) + num_packets > buffer->num_packets) { - /* The read wraps around the end of the buffer, do it in two parts */ - uint32_t initial_read_size = (buffer->num_packets - cpacketbuffer_read_index(buffer)) * buffer->packet_size; - - memcpy(buf, read_start, initial_read_size); - memcpy((uint8_t *)buf + initial_read_size, buffer->buffer, num_bytes - initial_read_size); - } else - memcpy(buf, read_start, num_bytes); - - /* CPU memory barrier */ - wmb(); - /* Update the read index with how many packets we pulled out of the stream */ - cpacketbuffer_advance_index(buffer->read_index, num_packets, buffer->num_packets); - /* CPU memory barrier */ - wmb(); - - return num_bytes; -} - -const void *cpacketbuffer_peek(struct cpacketbuffer *buffer, const void *current_packet) -{ - uint32_t next_packet_index; - - SCSC_TAG_DBG4(CPKTBUFF, "*buffer->read_index=0x%x *buffer->write_index=0x%x\n", - *buffer->read_index, *buffer->write_index); - if (current_packet == NULL) - /* Reading the first available packet */ - next_packet_index = cpacketbuffer_read_index(buffer); - else - /* Reading the next available packet past the current value of current_packet */ - next_packet_index = cpacketbuffer_address_to_index(buffer, - (const uint8_t *)current_packet + buffer->packet_size); - - if (next_packet_index == cpacketbuffer_write_index(buffer)) - /* No more packets available */ - return NULL; - - return cpacketbuffer_index_to_address(buffer, &next_packet_index); -} - -void cpacketbuffer_peek_complete(struct cpacketbuffer *buffer, const void *current_packet) -{ - if (current_packet == NULL) - return; - - /* The address we're given is the last packet read, so the new read index is for the next one */ - *buffer->read_index = cpacketbuffer_address_to_index(buffer, - (const uint8_t *)current_packet + buffer->packet_size); - /* CPU memory barrier */ - wmb(); -} - -bool cpacketbuffer_is_empty(const struct cpacketbuffer *buffer) -{ - return cpacketbuffer_read_index(buffer) == cpacketbuffer_write_index(buffer); -} - -bool cpacketbuffer_is_full(const struct cpacketbuffer *buffer) -{ - return (cpacketbuffer_write_index(buffer) + 1) % buffer->num_packets == cpacketbuffer_read_index(buffer); -} - -uint32_t cpacketbuffer_free_space(const struct cpacketbuffer *buffer) -{ - uint32_t base_free_space = cpacketbuffer_write_index(buffer) >= cpacketbuffer_read_index(buffer) ? - cpacketbuffer_read_index(buffer) + buffer->num_packets - cpacketbuffer_write_index(buffer) : - cpacketbuffer_read_index(buffer) - cpacketbuffer_write_index(buffer); - - /* Subtract the full/empty identification reserved slot from the free space */ - return base_free_space - 1; -} - -uint32_t cpacketbuffer_packet_size(const struct cpacketbuffer *buffer) -{ - return buffer->packet_size; -} - -void cpacketbuffer_config_serialise(const struct cpacketbuffer *buffer, struct mxcbufconf *buf_conf) -{ - scsc_mifram_ref mifram_ref; - struct scsc_mif_abs *mif; - - mif = scsc_mx_get_mif_abs(buffer->mx); - - mif->get_mifram_ref(mif, buffer->buffer, &mifram_ref); - buf_conf->buffer_loc = mifram_ref; - buf_conf->num_packets = buffer->num_packets; - buf_conf->packet_size = buffer->packet_size; - mif->get_mifram_ref(mif, buffer->read_index, &mifram_ref); - buf_conf->read_index_loc = mifram_ref; - mif->get_mifram_ref(mif, buffer->write_index, &mifram_ref); - buf_conf->write_index_loc = mifram_ref; - - mxcbufconf_print(buf_conf); -} - -void cpacketbuffer_log(const struct cpacketbuffer *buffer, enum scsc_log_level log_level) -{ - const uint8_t *read_start = cpacketbuffer_index_to_address((struct cpacketbuffer *)buffer, buffer->read_index); - - SCSC_TAG_LVL((CPKTBUFF), log_level, - "read_index=0x%x write_index=0x%x, read_start[0]=0x%08x\n", - *buffer->read_index, *buffer->write_index, - *(uint32_t *)read_start); -} - diff --git a/drivers/misc/samsung/scsc/cpacket_buffer.h b/drivers/misc/samsung/scsc/cpacket_buffer.h deleted file mode 100644 index 884cf0b8ad32..000000000000 --- a/drivers/misc/samsung/scsc/cpacket_buffer.h +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * Circular buffer backed packet stream (Interface) - */ - -#ifndef CPACKET_BUFFER_H__ -#define CPACKET_BUFFER_H__ - -/* Uses */ -#include -#include "scsc_mx_impl.h" -#include "mxconf.h" -#include "scsc_logring_common.h" - -struct cpacketbuffer; - -/** - * Initialises the circular buffer. - * The memory buffer length must be a multiple of the packet size. - */ -int cpacketbuffer_init(struct cpacketbuffer *buffer, uint32_t num_packets, uint32_t packet_size, struct scsc_mx *mx); -void cpacketbuffer_release(struct cpacketbuffer *buffer); - -/** - * Reads the gven amount of data from the buffer, copying it to the provided address. - * This automatically removes the read data from the buffer. - * - * If the amount of data requested is not a multiple of the packet size - * only the requested number of bytes will be read, but the partially read packet - * will still be removed from the buffer. - * - * Returns true if the packet was read. - */ -uint32_t cpacketbuffer_read(struct cpacketbuffer *buffer, void *buf, uint32_t num_bytes); - -/** - * Returns a pointer to the next packet of data within the buffer, without - * removing it. This can be used to processss data in place without needing to - * copy it first. - * - * If multiple packets are present these can be read in turn by setting the value - * of current_packet to the returned value from the previous call to cpacketbuffer_peek. - * - * cpacketbuffer_peek_complete must be called to remove the packet(s) from the buffer. - * - * Returns a pointer to the beginning of the packet to read, or NULL if there is no - * packet to process. - * - * Example use: - * // Get the first data packet - * void *current_packet = cpacketbuffer_peek( buffer, NULL ); - * void *last_packet = NULL; - * while( current_packet != NULL ) - * { - * // Process data packet - * ... - * - * // Get the next data packet - * last_packet = current_packet; - * current_packet = cpacketbuffer_peek( buffer, current_packet ); - * } - * - * // Remove all processed packets from the buffer - * if( last_packet != NULL ) - * { - * cpacketbuffer_peek_complete( buffer, last_packet ); - * } - */ -const void *cpacketbuffer_peek(struct cpacketbuffer *buffer, const void *current_packet); - -/** - * Removes all packets from the buffer up to and including the given - * packet. - * - * This must be called after using cpacketbuffer_peek to indicate that packet(s) - * can be removed from the buffer. - */ -void cpacketbuffer_peek_complete(struct cpacketbuffer *buffer, const void *packet); - -/** - * Writes a number of bytes to the buffer. This will always use up whole packets in the buffer - * even if the amount of data written is not an exact multiple of the packet size. - * - * Returns true if the data was written, false if there is not enough free space in the buffer. - */ -bool cpacketbuffer_write(struct cpacketbuffer *buffer, const void *buf, uint32_t num_bytes); - -/** - * Writes a set of non-contiguous data blocks to the buffer as a contiguous set. - * This will always use up whole packets even if the - * amount of data written is not an exact multiple of the packet size. - * - * Returns true if the blocks were written, false if there is not enough - * free space in the buffer for all the blocks. - */ -bool cpacketbuffer_write_gather(struct cpacketbuffer *buffer, const void **bufs, uint32_t *num_bytes, uint32_t num_bufs); - -/** - * Returns the number of free packets in the buffer. - */ -uint32_t cpacketbuffer_free_space(const struct cpacketbuffer *buffer); - -/** - * Returns true if the buffer is empty. - */ -bool cpacketbuffer_is_empty(const struct cpacketbuffer *buffer); - -/** - * Returns true if the buffer is full. - */ -bool cpacketbuffer_is_full(const struct cpacketbuffer *buffer); - -/** - * Returns the packet size the buffer was initialised with. This is the same value - * as the packet_size argument passed to cpacketbuffer_init(). - */ -uint32_t cpacketbuffer_packet_size(const struct cpacketbuffer *buffer); - -void cpacketbuffer_config_serialise(const struct cpacketbuffer *buffer, struct mxcbufconf *buf_conf); - -/** - * Log the state of this packet buffer at the specified log_level. - */ -void cpacketbuffer_log(const struct cpacketbuffer *buffer, enum scsc_log_level log_level); - -/** - * Buffer context object. - */ -struct cpacketbuffer { - struct scsc_mx *mx; - void *buffer; /* Buffer location */ - uint32_t num_packets; /* Total number of packets that can be stored in the buffer */ - uint32_t packet_size; /* Size of each individual packet within the buffer */ - - /** Pointers to 32bit R/W indexes - these should point to uint32_ts */ - uint32_t *read_index; /* Pointer to the location of the read index, which - * contains the index of the next packet to read. */ - uint32_t *write_index; /* Pointer to the location of the write index, which - * contains the index after the last packet written. */ -}; - -#endif /* CPACKET_BUFFER_H__ */ diff --git a/drivers/misc/samsung/scsc/functor.h b/drivers/misc/samsung/scsc/functor.h deleted file mode 100644 index e6dabde3f550..000000000000 --- a/drivers/misc/samsung/scsc/functor.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -****************************************************************************/ - -#ifndef __FUNCTOR_H -#define __FUNCTOR_H - -/** - * Minimal Functor (no returns, no args other than self). - */ -struct functor { - /** - * The callback invoked by functor_call(). - * - * A pointer to the functor itself is passed to the call. - * - * Typically the implementation wil upcast this (container_of) - * to access a container context. - */ - void (*call)(struct functor *f); -}; - -/** - * Initialise this functor. - */ -static inline void functor_init(struct functor *f, void (*call)(struct functor *f)) -{ - f->call = call; -} - -/** - * Invoke this functor. - */ -static inline void functor_call(struct functor *f) -{ - f->call(f); -} - -#endif /* __FUNCTOR_H */ - diff --git a/drivers/misc/samsung/scsc/fw_panic_record.c b/drivers/misc/samsung/scsc/fw_panic_record.c deleted file mode 100644 index 4d31ddcb792d..000000000000 --- a/drivers/misc/samsung/scsc/fw_panic_record.c +++ /dev/null @@ -1,178 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include -#include -#include "panic_record_r4_defs.h" - -#define PANIC_RECORD_CKSUM_SEED 0xa5a5a5a5 -/* - * version 2 r4 panic record defs - */ -#define R4_PANIC_RECORD_VERSION_2 2 -#define R4_PANIC_RECORD_LENGTH_INDEX_V2 1 -#define R4_PANIC_RECORD_MAX_LENGTH_V2 256 - -/* - * version 1 mr4 panic record defs - */ -#define M4_PANIC_RECORD_VERSION_1 1 -#define M4_PANIC_RECORD_VERSION_INDEX 0 -#define M4_PANIC_RECORD_LENGTH_INDEX 1 -#define M4_PANIC_RECORD_MAX_LENGTH 256 - -#define R4_PANIC_RECORD_V2_SYMPATHETIC_PANIC_FLAG_INDEX 51 -#define M4_PANIC_RECORD_SYMPATHETIC_PANIC_FLAG_INDEX 39 - -/** - * Compute 32bit xor of specified seed value and data. - * - * @param seed Initial seed value. - * @param data Array of uint32s to be xored - * @param len Number of uint32s to be xored - * - * @return Computed 32bit xor of specified seed value and data. - */ -static u32 xor32(uint32_t seed, const u32 data[], size_t len) -{ - const u32 *i; - u32 xor = seed; - - for (i = data; i != data + len; ++i) - xor ^= *i; - return xor; -} - -static void panic_record_dump(u32 *panic_record, u32 panic_record_length, bool r4) -{ - int i; - - SCSC_TAG_INFO(FW_PANIC, "%s panic record dump(length=%d):\n", - r4 ? "R4" : "M4", panic_record_length); - for (i = 0; i < panic_record_length; i++) - SCSC_TAG_INFO(FW_PANIC, "%s_panic_record[%d] = %08x\n", - r4 ? "r4" : "m4", i, panic_record[i]); -} - -static bool fw_parse_r4_panic_record_v2(u32 *r4_panic_record, u32 *r4_panic_record_length) -{ - u32 panic_record_cksum; - u32 calculated_cksum; - u32 panic_record_length = *(r4_panic_record + R4_PANIC_RECORD_LENGTH_INDEX_V2) / 4; - - SCSC_TAG_INFO(FW_PANIC, "panic_record_length: %d\n", panic_record_length); - - if (panic_record_length < R4_PANIC_RECORD_MAX_LENGTH_V2) { - panic_record_cksum = *(r4_panic_record + panic_record_length - 1); - calculated_cksum = xor32(PANIC_RECORD_CKSUM_SEED, r4_panic_record, panic_record_length - 1); - if (calculated_cksum == panic_record_cksum) { - SCSC_TAG_INFO(FW_PANIC, "panic_record_cksum OK: %08x\n", - calculated_cksum); - panic_record_dump(r4_panic_record, panic_record_length, true); - *r4_panic_record_length = panic_record_length; - return true; - } else { - SCSC_TAG_ERR(FW_PANIC, "BAD panic_record_cksum: 0x%x calculated_cksum: 0x%x\n", - panic_record_cksum, calculated_cksum); - } - } else { - SCSC_TAG_ERR(FW_PANIC, "BAD panic_record_length: %d\n", - panic_record_length); - } - return false; -} - -static bool fw_parse_m4_panic_record_v1(u32 *m4_panic_record, u32 *m4_panic_record_length) -{ - u32 panic_record_cksum; - u32 calculated_cksum; - u32 panic_record_length = *(m4_panic_record + M4_PANIC_RECORD_LENGTH_INDEX) / 4; - - SCSC_TAG_INFO(FW_PANIC, "panic_record_length: %d\n", panic_record_length); - - if (panic_record_length < M4_PANIC_RECORD_MAX_LENGTH) { - panic_record_cksum = *(m4_panic_record + panic_record_length - 1); - calculated_cksum = xor32(PANIC_RECORD_CKSUM_SEED, m4_panic_record, panic_record_length - 1); - if (calculated_cksum == panic_record_cksum) { - SCSC_TAG_INFO(FW_PANIC, "panic_record_cksum OK: %08x\n", - calculated_cksum); - panic_record_dump(m4_panic_record, panic_record_length, false); - *m4_panic_record_length = panic_record_length; - return true; - } else { - SCSC_TAG_ERR(FW_PANIC, "BAD panic_record_cksum: 0x%x calculated_cksum: 0x%x\n", - panic_record_cksum, calculated_cksum); - } - } else { - SCSC_TAG_ERR(FW_PANIC, "BAD panic_record_length: %d\n", - panic_record_length); - } - return false; -} - -bool fw_parse_r4_panic_record(u32 *r4_panic_record, u32 *r4_panic_record_length) -{ - u32 panic_record_version = *(r4_panic_record + PANIC_RECORD_R4_VERSION_INDEX); - - SCSC_TAG_INFO(FW_PANIC, "panic_record_version: %d\n", panic_record_version); - - switch (panic_record_version) { - default: - SCSC_TAG_ERR(FW_PANIC, "BAD panic_record_version: %d\n", - panic_record_version); - break; - case R4_PANIC_RECORD_VERSION_2: - return fw_parse_r4_panic_record_v2(r4_panic_record, r4_panic_record_length); - } - return false; -} - -bool fw_parse_m4_panic_record(u32 *m4_panic_record, u32 *m4_panic_record_length) -{ - u32 panic_record_version = *(m4_panic_record + M4_PANIC_RECORD_VERSION_INDEX); - - SCSC_TAG_INFO(FW_PANIC, "panic_record_version: %d\n", panic_record_version); - switch (panic_record_version) { - default: - SCSC_TAG_ERR(FW_PANIC, "BAD panic_record_version: %d\n", - panic_record_version); - break; - case M4_PANIC_RECORD_VERSION_1: - return fw_parse_m4_panic_record_v1(m4_panic_record, m4_panic_record_length); - } - return false; -} - -bool fw_parse_get_r4_sympathetic_panic_flag(u32 *r4_panic_record) -{ - bool sympathetic_panic_flag = *(r4_panic_record + R4_PANIC_RECORD_V2_SYMPATHETIC_PANIC_FLAG_INDEX); - - return sympathetic_panic_flag; -} - -bool fw_parse_get_m4_sympathetic_panic_flag(u32 *m4_panic_record) -{ - bool sympathetic_panic_flag = *(m4_panic_record + M4_PANIC_RECORD_SYMPATHETIC_PANIC_FLAG_INDEX); - - return sympathetic_panic_flag; -} - -int panic_record_dump_buffer(char *processor, u32 *panic_record, - u32 panic_record_length, char *buffer, size_t blen) -{ - int i, used; - - if (!processor) - processor = "WLBT"; - - used = snprintf(buffer, blen, "%s panic record dump(length=%d):\n", - processor, panic_record_length); - for (i = 0; i < panic_record_length && used < blen; i++) - used += snprintf(buffer + used, blen - used, "%s_panic_record[%d] = %08x\n", - processor, i, panic_record[i]); - - return used; -} diff --git a/drivers/misc/samsung/scsc/fw_panic_record.h b/drivers/misc/samsung/scsc/fw_panic_record.h deleted file mode 100644 index 209ae35c237a..000000000000 --- a/drivers/misc/samsung/scsc/fw_panic_record.h +++ /dev/null @@ -1,18 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef FW_PANIC_RECORD_H__ -#define FW_PANIC_RECORD_H__ - -bool fw_parse_r4_panic_record(u32 *r4_panic_record, u32 *r4_panic_record_length); -bool fw_parse_m4_panic_record(u32 *m4_panic_record, u32 *m4_panic_record_length); - -bool fw_parse_get_r4_sympathetic_panic_flag(u32 *r4_panic_record); -bool fw_parse_get_m4_sympathetic_panic_flag(u32 *m4_panic_record); - -int panic_record_dump_buffer(char *processor, u32 *panic_record, - u32 panic_record_length, char *buffer, size_t blen); -#endif /* FW_PANIC_RECORD_H__ */ diff --git a/drivers/misc/samsung/scsc/fwhdr.c b/drivers/misc/samsung/scsc/fwhdr.c deleted file mode 100644 index b4aaabf97389..000000000000 --- a/drivers/misc/samsung/scsc/fwhdr.c +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include "fwhdr.h" - -/* - * The Maxwell Firmware Header Format is defined in SC-505846-SW - */ - -#define FWHDR_02_TRAMPOLINE_OFFSET 0 -#define FWHDR_02_MAGIC_OFFSET 8 -#define FWHDR_02_VERSION_MINOR_OFFSET 12 -#define FWHDR_02_VERSION_MAJOR_OFFSET 14 -#define FWHDR_02_LENGTH_OFFSET 16 -#define FWHDR_02_FIRMWARE_API_VERSION_MINOR_OFFSET 20 -#define FWHDR_02_FIRMWARE_API_VERSION_MAJOR_OFFSET 22 -#define FWHDR_02_FIRMWARE_CRC_OFFSET 24 -#define FWHDR_02_CONST_FW_LENGTH_OFFSET 28 -#define FWHDR_02_CONST_CRC_OFFSET 32 -#define FWHDR_02_FIRMWARE_RUNTIME_LENGTH_OFFSET 36 -#define FWHDR_02_FIRMWARE_ENTRY_POINT_OFFSET 40 -#define FWHDR_02_BUILD_ID_OFFSET 48 -#define FWHDR_02_R4_PANIC_RECORD_OFFSET_OFFSET 176 -#define FWHDR_02_M4_PANIC_RECORD_OFFSET_OFFSET 180 -#define FWHDR_02_TTID_OFFSET 184 - -/* - * Firmware header format for version 1.0 is same as version for 0.2 - */ -#define FWHDR_02_TRAMPOLINE(__fw) (*((u32 *)(__fw + FWHDR_02_TRAMPOLINE_OFFSET))) -#define FWHDR_02_HEADER_FIRMWARE_ENTRY_POINT(__fw) (*((u32 *)(__fw + FWHDR_02_FIRMWARE_ENTRY_POINT_OFFSET))) -#define FWHDR_02_HEADER_FIRMWARE_RUNTIME_LENGTH(__fw) (*((u32 *)(__fw + FWHDR_02_FIRMWARE_RUNTIME_LENGTH_OFFSET))) -#define FWHDR_02_HEADER_VERSION_MAJOR(__fw) (*((u16 *)(__fw + FWHDR_02_VERSION_MAJOR_OFFSET))) -#define FWHDR_02_HEADER_VERSION_MINOR(__fw) (*((u16 *)(__fw + FWHDR_02_VERSION_MINOR_OFFSET))) -#define FWHDR_02_HEADER_FIRMWARE_API_VERSION_MINOR(__fw) (*((u16 *)(__fw + FWHDR_02_FIRMWARE_API_VERSION_MINOR_OFFSET))) -#define FWHDR_02_HEADER_FIRMWARE_API_VERSION_MAJOR(__fw) (*((u16 *)(__fw + FWHDR_02_FIRMWARE_API_VERSION_MAJOR_OFFSET))) -#define FWHDR_02_FW_CRC32(__fw) (*((u32 *)(__fw + FWHDR_02_FIRMWARE_CRC_OFFSET))) -#define FWHDR_02_HDR_LENGTH(__fw) (*((u32 *)(__fw + FWHDR_02_LENGTH_OFFSET))) -#define FWHDR_02_HEADER_CRC32(__fw) (*((u32 *)(__fw + (FWHDR_02_HDR_LENGTH(__fw)) - sizeof(u32)))) -#define FWHDR_02_CONST_CRC32(__fw) (*((u32 *)(__fw + FWHDR_02_CONST_CRC_OFFSET))) -#define FWHDR_02_CONST_FW_LENGTH(__fw) (*((u32 *)(__fw + FWHDR_02_CONST_FW_LENGTH_OFFSET))) -#define FWHDR_02_R4_PANIC_RECORD_OFFSET(__fw) (*((u32 *)(__fw + FWHDR_02_R4_PANIC_RECORD_OFFSET_OFFSET))) -#define FWHDR_02_M4_PANIC_RECORD_OFFSET(__fw) (*((u32 *)(__fw + FWHDR_02_M4_PANIC_RECORD_OFFSET_OFFSET))) - -/* firmware header has a panic record if the firmware header length is at least 192 bytes long */ -#define MIN_HEADER_LENGTH_WITH_PANIC_RECORD 188 - -#define FWHDR_MAGIC_STRING "smxf" - -static bool fwhdr_parse_v02(char *fw, struct fwhdr *fwhdr) -{ - if (!memcmp(fw + FWHDR_02_MAGIC_OFFSET, FWHDR_MAGIC_STRING, sizeof(FWHDR_MAGIC_STRING) - 1)) { - fwhdr->firmware_entry_point = FWHDR_02_HEADER_FIRMWARE_ENTRY_POINT(fw); - fwhdr->hdr_major = FWHDR_02_HEADER_VERSION_MAJOR(fw); - fwhdr->hdr_minor = FWHDR_02_HEADER_VERSION_MINOR(fw); - fwhdr->fwapi_major = FWHDR_02_HEADER_FIRMWARE_API_VERSION_MAJOR(fw); - fwhdr->fwapi_minor = FWHDR_02_HEADER_FIRMWARE_API_VERSION_MINOR(fw); - fwhdr->fw_crc32 = FWHDR_02_FW_CRC32(fw); - fwhdr->const_crc32 = FWHDR_02_CONST_CRC32(fw); - fwhdr->header_crc32 = FWHDR_02_HEADER_CRC32(fw); - fwhdr->const_fw_length = FWHDR_02_CONST_FW_LENGTH(fw); - fwhdr->hdr_length = FWHDR_02_HDR_LENGTH(fw); - fwhdr->fw_runtime_length = FWHDR_02_HEADER_FIRMWARE_RUNTIME_LENGTH(fw); - SCSC_TAG_INFO(FW_LOAD, "hdr_length=%d\n", fwhdr->hdr_length); - fwhdr->r4_panic_record_offset = FWHDR_02_R4_PANIC_RECORD_OFFSET(fw); - fwhdr->m4_panic_record_offset = FWHDR_02_M4_PANIC_RECORD_OFFSET(fw); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - fwhdr->m4_1_panic_record_offset = FWHDR_02_M4_PANIC_RECORD_OFFSET(fw); -#endif - return true; - } - return false; -} - -static char *fwhdr_get_build_id_v02(char *fw, struct fwhdr *fwhdr) -{ - if (!memcmp(fw + FWHDR_02_MAGIC_OFFSET, FWHDR_MAGIC_STRING, sizeof(FWHDR_MAGIC_STRING) - 1)) - return fw + FWHDR_02_BUILD_ID_OFFSET; - return NULL; -} - -static char *fwhdr_get_ttid_v02(char *fw, struct fwhdr *fwhdr) -{ - if (fwhdr->hdr_length < FWHDR_02_TTID_OFFSET) - return NULL; - if (!memcmp(fw + FWHDR_02_MAGIC_OFFSET, FWHDR_MAGIC_STRING, sizeof(FWHDR_MAGIC_STRING) - 1)) - return fw + FWHDR_02_TTID_OFFSET; - return NULL; -} - -bool fwhdr_parse(char *fw, struct fwhdr *fwhdr) -{ - return fwhdr_parse_v02(fw, fwhdr); -} - -char *fwhdr_get_build_id(char *fw, struct fwhdr *fwhdr) -{ - return fwhdr_get_build_id_v02(fw, fwhdr); -} - -char *fwhdr_get_ttid(char *fw, struct fwhdr *fwhdr) -{ - return fwhdr_get_ttid_v02(fw, fwhdr); -} diff --git a/drivers/misc/samsung/scsc/fwhdr.h b/drivers/misc/samsung/scsc/fwhdr.h deleted file mode 100644 index d85118859156..000000000000 --- a/drivers/misc/samsung/scsc/fwhdr.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef FWHDR_H -#define FWHDR_H - -#define FW_BUILD_ID_SZ 128 -#define FW_TTID_SZ 32 - -struct fwhdr { - u16 hdr_major; - u16 hdr_minor; - - u16 fwapi_major; - u16 fwapi_minor; - - u32 firmware_entry_point; - u32 fw_runtime_length; - - u32 fw_crc32; - u32 const_crc32; - u32 header_crc32; - - u32 const_fw_length; - u32 hdr_length; - u32 r4_panic_record_offset; - u32 m4_panic_record_offset; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - u32 m4_1_panic_record_offset; -#endif -}; - -bool fwhdr_parse(char *fw, struct fwhdr *fwhdr); -char *fwhdr_get_build_id(char *fw, struct fwhdr *fwhdr); -char *fwhdr_get_ttid(char *fw, struct fwhdr *fwhdr); - -#endif /* FWHDR_H */ diff --git a/drivers/misc/samsung/scsc/fwimage.c b/drivers/misc/samsung/scsc/fwimage.c deleted file mode 100644 index 6e7bd3375fc2..000000000000 --- a/drivers/misc/samsung/scsc/fwimage.c +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include "fwimage.h" - -int fwimage_check_fw_header_crc(char *fw, u32 hdr_length, u32 header_crc32) -{ - u32 header_crc32_calculated; - - /* - * The last 4-bytes are header CRC - */ - header_crc32_calculated = ether_crc(hdr_length - sizeof(u32), fw); - if (header_crc32_calculated != header_crc32) { - SCSC_TAG_ERR(FW_LOAD, "CRC32 doesn't match: header_crc32_calculated=%d header_crc32=%d\n", - header_crc32_calculated, header_crc32); - return -EINVAL; - } - SCSC_TAG_DEBUG(FW_LOAD, "CRC32 OK: header_crc32_calculated=%d header_crc32=%d\n", - header_crc32_calculated, header_crc32); - return 0; -} - -int fwimage_check_fw_const_section_crc(char *fw, u32 const_crc32, u32 const_fw_length, u32 hdr_length) -{ - u32 const_crc32_calculated; - - const_crc32_calculated = ether_crc(const_fw_length - hdr_length, fw + hdr_length); - if (const_crc32_calculated != const_crc32) { - SCSC_TAG_ERR(FW_LOAD, "CRC32 doesn't match: const_crc32_calculated=%d const_crc32=%d\n", - const_crc32_calculated, const_crc32); - return -EINVAL; - } - SCSC_TAG_DEBUG(FW_LOAD, "CRC32 OK: const_crc32_calculated=%d const_crc32=%d\n", - const_crc32_calculated, const_crc32); - return 0; -} - -int fwimage_check_fw_crc(char *fw, u32 fw_image_length, u32 hdr_length, u32 fw_crc32) -{ - u32 fw_crc32_calculated; - - fw_crc32_calculated = ether_crc(fw_image_length - hdr_length, fw + hdr_length); - if (fw_crc32_calculated != fw_crc32) { - SCSC_TAG_ERR(FW_LOAD, "CRC32 doesn't match: fw_crc32_calculated=%d fw_crc32=%d\n", - fw_crc32_calculated, fw_crc32); - return -EINVAL; - } - SCSC_TAG_DEBUG(FW_LOAD, "CRC32 OK: fw_crc32_calculated=%d fw_crc32=%d\n", - fw_crc32_calculated, fw_crc32); - return 0; -} diff --git a/drivers/misc/samsung/scsc/fwimage.h b/drivers/misc/samsung/scsc/fwimage.h deleted file mode 100644 index 88e0d838b706..000000000000 --- a/drivers/misc/samsung/scsc/fwimage.h +++ /dev/null @@ -1,14 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef FWIMAGE_H -#define FWIMAGE_H - -int fwimage_check_fw_header_crc(char *fw, u32 hdr_length, u32 header_crc32); -int fwimage_check_fw_const_section_crc(char *fw, u32 const_crc32, u32 const_fw_length, u32 hdr_length); -int fwimage_check_fw_crc(char *fw, u32 fw_runtime_length, u32 hdr_length, u32 fw_crc32); - -#endif /* FWIMAGE_H */ diff --git a/drivers/misc/samsung/scsc/gdb_transport.c b/drivers/misc/samsung/scsc/gdb_transport.c deleted file mode 100644 index 84e37a6396db..000000000000 --- a/drivers/misc/samsung/scsc/gdb_transport.c +++ /dev/null @@ -1,263 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** Implements */ -#include "gdb_transport.h" - -/** Uses */ -#include -#include -#include -#include "mifintrbit.h" - -struct clients_node { - struct list_head list; - struct gdb_transport_client *gdb_client; -}; - -struct gdb_transport_node { - struct list_head list; - struct gdb_transport *gdb_transport; -}; - -static struct gdb_transport_module { - struct list_head clients_list; - struct list_head gdb_transport_list; -} gdb_transport_module = { - .clients_list = LIST_HEAD_INIT(gdb_transport_module.clients_list), - .gdb_transport_list = LIST_HEAD_INIT(gdb_transport_module.gdb_transport_list) -}; - -/** Handle incoming packets and pass to handler */ -static void gdb_input_irq_handler(int irq, void *data) -{ - struct gdb_transport *gdb_transport = (struct gdb_transport *)data; - struct scsc_mif_abs *mif_abs; - u32 num_bytes; - u32 alloc_bytes; - char *buf; - - SCSC_TAG_DEBUG(GDB_TRANS, "Handling write signal.\n"); - - /* 1st length */ - /* Clear the interrupt first to ensure we can't possibly miss one */ - mif_abs = scsc_mx_get_mif_abs(gdb_transport->mx); - mif_abs->irq_bit_clear(mif_abs, irq); - - while (mif_stream_read(&gdb_transport->mif_istream, &num_bytes, sizeof(uint32_t))) { - SCSC_TAG_DEBUG(GDB_TRANS, "Transferring %d byte payload to handler.\n", num_bytes); - if (num_bytes > 0 && num_bytes - < (GDB_TRANSPORT_BUF_LENGTH - sizeof(uint32_t))) { - alloc_bytes = sizeof(char) * num_bytes; - /* This is called in atomic context so must use kmalloc with GFP_ATOMIC flag */ - buf = kmalloc(alloc_bytes, GFP_ATOMIC); - /* 2nd payload (msg) */ - mif_stream_read(&gdb_transport->mif_istream, buf, num_bytes); - gdb_transport->channel_handler_fn(buf, num_bytes, gdb_transport->channel_handler_data); - kfree(buf); - } else { - SCSC_TAG_ERR(GDB_TRANS, "Incorrect num_bytes: 0x%08x\n", num_bytes); - mif_stream_log(&gdb_transport->mif_istream, SCSC_ERR); - } - } -} - - -/** MIF Interrupt handler for acknowledging reads made by the AP */ -static void gdb_output_irq_handler(int irq, void *data) -{ - struct scsc_mif_abs *mif_abs; - struct gdb_transport *gdb_transport = (struct gdb_transport *)data; - - SCSC_TAG_DEBUG(GDB_TRANS, "Ignoring read signal.\n"); - - /* Clear the interrupt first to ensure we can't possibly miss one */ - /* The FW read some data from the output stream. - * Currently we do not care, so just clear the interrupt. */ - mif_abs = scsc_mx_get_mif_abs(gdb_transport->mx); - mif_abs->irq_bit_clear(mif_abs, irq); -} - -static void gdb_transport_probe_registered_clients(struct gdb_transport *gdb_transport) -{ - bool client_registered = false; - struct clients_node *gdb_client_node, *gdb_client_next; - struct scsc_mif_abs *mif_abs; - char *dev_uid; - - /* Traverse Linked List for each mif_driver node */ - list_for_each_entry_safe(gdb_client_node, gdb_client_next, &gdb_transport_module.clients_list, list) { - /* Get UID */ - mif_abs = scsc_mx_get_mif_abs(gdb_transport->mx); - dev_uid = mif_abs->get_uid(mif_abs); - gdb_client_node->gdb_client->probe(gdb_client_node->gdb_client, gdb_transport, dev_uid); - client_registered = true; - } - if (client_registered == false) - SCSC_TAG_INFO(GDB_TRANS, "No clients registered\n"); -} - -void gdb_transport_release(struct gdb_transport *gdb_transport) -{ - struct clients_node *gdb_client_node, *gdb_client_next; - struct gdb_transport_node *gdb_transport_node, *gdb_transport_node_next; - bool match = false; - - list_for_each_entry_safe(gdb_transport_node, gdb_transport_node_next, &gdb_transport_module.gdb_transport_list, list) { - if (gdb_transport_node->gdb_transport == gdb_transport) { - match = true; - SCSC_TAG_INFO(GDB_TRANS, "release client\n"); - /* Wait for client to close */ - mutex_lock(&gdb_transport->channel_open_mutex); - /* Need to notify clients using the transport has been released */ - list_for_each_entry_safe(gdb_client_node, gdb_client_next, &gdb_transport_module.clients_list, list) { - gdb_client_node->gdb_client->remove(gdb_client_node->gdb_client, gdb_transport); - } - mutex_unlock(&gdb_transport->channel_open_mutex); - list_del(&gdb_transport_node->list); - kfree(gdb_transport_node); - } - } - if (match == false) - SCSC_TAG_INFO(GDB_TRANS, "No match for given scsc_mif_abs\n"); - - mif_stream_release(&gdb_transport->mif_istream); - mif_stream_release(&gdb_transport->mif_ostream); -} - -void gdb_transport_config_serialise(struct gdb_transport *gdb_transport, - struct mxtransconf *trans_conf) -{ - mif_stream_config_serialise(&gdb_transport->mif_istream, &trans_conf->to_ap_stream_conf); - mif_stream_config_serialise(&gdb_transport->mif_ostream, &trans_conf->from_ap_stream_conf); -} - - -/** Public functions */ -int gdb_transport_init(struct gdb_transport *gdb_transport, struct scsc_mx *mx, enum gdb_transport_enum type) -{ - int r; - uint32_t mem_length = GDB_TRANSPORT_BUF_LENGTH; - uint32_t packet_size = 4; - uint32_t num_packets; - struct gdb_transport_node *gdb_transport_node; - - gdb_transport_node = kzalloc(sizeof(*gdb_transport_node), GFP_KERNEL); - if (!gdb_transport_node) - return -EIO; - - memset(gdb_transport, 0, sizeof(struct gdb_transport)); - num_packets = mem_length / packet_size; - mutex_init(&gdb_transport->channel_handler_mutex); - mutex_init(&gdb_transport->channel_open_mutex); - gdb_transport->mx = mx; - - if (type == GDB_TRANSPORT_M4) - r = mif_stream_init(&gdb_transport->mif_istream, SCSC_MIF_ABS_TARGET_M4, MIF_STREAM_DIRECTION_IN, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_ALLOC, gdb_input_irq_handler, gdb_transport); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - else if (type == GDB_TRANSPORT_M4_1) - r = mif_stream_init(&gdb_transport->mif_istream, SCSC_MIF_ABS_TARGET_M4_1, MIF_STREAM_DIRECTION_IN, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_ALLOC, gdb_input_irq_handler, gdb_transport); -#endif - else - r = mif_stream_init(&gdb_transport->mif_istream, SCSC_MIF_ABS_TARGET_R4, MIF_STREAM_DIRECTION_IN, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_ALLOC, gdb_input_irq_handler, gdb_transport); - if (r) { - kfree(gdb_transport_node); - return r; - } - - if (type == GDB_TRANSPORT_M4) - r = mif_stream_init(&gdb_transport->mif_ostream, SCSC_MIF_ABS_TARGET_M4, MIF_STREAM_DIRECTION_OUT, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_RESERVED, gdb_output_irq_handler, gdb_transport); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - else if (type == GDB_TRANSPORT_M4_1) - r = mif_stream_init(&gdb_transport->mif_ostream, SCSC_MIF_ABS_TARGET_M4_1, MIF_STREAM_DIRECTION_OUT, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_RESERVED, gdb_output_irq_handler, gdb_transport); -#endif - else - r = mif_stream_init(&gdb_transport->mif_ostream, SCSC_MIF_ABS_TARGET_R4, MIF_STREAM_DIRECTION_OUT, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_RESERVED, gdb_output_irq_handler, gdb_transport); - if (r) { - mif_stream_release(&gdb_transport->mif_istream); - kfree(gdb_transport_node); - return r; - } - - gdb_transport->channel_handler_fn = NULL; - gdb_transport->channel_handler_data = NULL; - - gdb_transport_node->gdb_transport = gdb_transport; - /* Add gdb_transport node */ - list_add_tail(&gdb_transport_node->list, &gdb_transport_module.gdb_transport_list); - gdb_transport->type = type; - gdb_transport_probe_registered_clients(gdb_transport); - return 0; -} - -void gdb_transport_send(struct gdb_transport *gdb_transport, void *message, uint32_t message_length) -{ - char msg[300]; - - if (message_length > sizeof(msg)) - return; - - memcpy(msg, message, message_length); - - mutex_lock(&gdb_transport->channel_handler_mutex); - /* 1st length */ - mif_stream_write(&gdb_transport->mif_ostream, &message_length, sizeof(uint32_t)); - /* 2nd payload (msg) */ - mif_stream_write(&gdb_transport->mif_ostream, message, message_length); - mutex_unlock(&gdb_transport->channel_handler_mutex); -} -EXPORT_SYMBOL(gdb_transport_send); - -void gdb_transport_register_channel_handler(struct gdb_transport *gdb_transport, - gdb_channel_handler handler, void *data) -{ - mutex_lock(&gdb_transport->channel_handler_mutex); - gdb_transport->channel_handler_fn = handler; - gdb_transport->channel_handler_data = (void *)data; - mutex_unlock(&gdb_transport->channel_handler_mutex); -} -EXPORT_SYMBOL(gdb_transport_register_channel_handler); - -int gdb_transport_register_client(struct gdb_transport_client *gdb_client) -{ - struct clients_node *gdb_client_node; - struct gdb_transport_node *gdb_transport_node; - struct scsc_mif_abs *mif_abs; - char *dev_uid; - - /* Add node in modules linked list */ - gdb_client_node = kzalloc(sizeof(*gdb_client_node), GFP_KERNEL); - if (!gdb_client_node) - return -ENOMEM; - - gdb_client_node->gdb_client = gdb_client; - list_add_tail(&gdb_client_node->list, &gdb_transport_module.clients_list); - - - /* Traverse Linked List for transport registered */ - list_for_each_entry(gdb_transport_node, &gdb_transport_module.gdb_transport_list, list) { - /* Get UID */ - mif_abs = scsc_mx_get_mif_abs(gdb_transport_node->gdb_transport->mx); - dev_uid = mif_abs->get_uid(mif_abs); - gdb_client->probe(gdb_client, gdb_transport_node->gdb_transport, dev_uid); - } - return 0; -} -EXPORT_SYMBOL(gdb_transport_register_client); - -void gdb_transport_unregister_client(struct gdb_transport_client *gdb_client) -{ - struct clients_node *gdb_client_node, *gdb_client_next; - - /* Traverse Linked List for each client_list */ - list_for_each_entry_safe(gdb_client_node, gdb_client_next, &gdb_transport_module.clients_list, list) { - if (gdb_client_node->gdb_client == gdb_client) { - list_del(&gdb_client_node->list); - kfree(gdb_client_node); - } - } -} -EXPORT_SYMBOL(gdb_transport_unregister_client); diff --git a/drivers/misc/samsung/scsc/gdb_transport.h b/drivers/misc/samsung/scsc/gdb_transport.h deleted file mode 100644 index 527d7efa9c67..000000000000 --- a/drivers/misc/samsung/scsc/gdb_transport.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * Maxwell gdb transport (Interface) - * - * Provides bi-directional communication between the firmware and the - * host. - * - * This interface also provides a utility method for sending messages across - * the stream. - */ - -#ifndef GDB_TRANSPORT_H__ -#define GDB_TRANSPORT_H__ - -/** Uses */ -#include -#include "mifstream.h" - -/* - * Initialising a buffer of 1 byte is never legitimate, do not allow it. - * The memory buffer length must be a multiple of the packet size. - */ -#define GDB_TRANSPORT_BUF_LENGTH (2 * 1024) - -struct gdb_transport; - -enum gdb_transport_enum { - GDB_TRANSPORT_R4 = 0, - GDB_TRANSPORT_M4, -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - GDB_TRANSPORT_M4_1, -#endif -}; -/** - * Transport channel callback handler. This will be invoked each time a message on a channel is - * received. Handlers may perform work within - * their callback implementation, but should not block. - * - * Note that the message pointer passed is only valid for the duration of the function call. - */ -typedef void (*gdb_channel_handler)(const void *message, size_t length, void *data); - -/** - * Sends a message to the AP across the given channel. - * - * This function is safe to call from any RTOS thread. - */ -void gdb_transport_send(struct gdb_transport *gdb_transport, - void *message, uint32_t message_length); - -/** - * Initialises the maxwell management transport and configures the necessary - * interrupt handlers. Called once during boot. - */ -int gdb_transport_init(struct gdb_transport *gdb_transport, struct scsc_mx *mx, enum gdb_transport_enum type); -void gdb_transport_release(struct gdb_transport *gdb_transport); - -/* - * Initialises the configuration area incl. Maxwell Infrastructure Configuration, - * MIF Management Transport Configuration and MIF Management Stream Configuration. - */ -void gdb_transport_config_serialise(struct gdb_transport *gdb_transport, struct mxtransconf *trans_conf); -void gdb_transport_set_error(struct gdb_transport *gdb_transport); - -struct gdb_transport { - struct scsc_mx *mx; - struct mif_stream mif_istream; - struct mif_stream mif_ostream; - /** Registered channel handlers for messages coming from the AP for each channel */ - gdb_channel_handler channel_handler_fn; - void *channel_handler_data; - struct mutex channel_handler_mutex; - struct mutex channel_open_mutex; - /* Transport processor type */ - enum gdb_transport_enum type; -}; - -struct gdb_transport_client { - char *name; - void (*probe)(struct gdb_transport_client *gdb_client, struct gdb_transport *gdb_transport, char *dev_uid); - void (*remove)(struct gdb_transport_client *gdb_client, struct gdb_transport *gdb_transport); -}; - -int gdb_transport_register_client(struct gdb_transport_client *gdb_client); -void gdb_transport_unregister_client(struct gdb_transport_client *gdb_client); -void gdb_transport_register_channel_handler(struct gdb_transport *gdb_transport, gdb_channel_handler handler, void *data); -void gdb_transport_register_char_device(struct scsc_mx *mx, struct gdb_transport **gdb_transport_handler); -#endif /* GDB_TRANSPORT_H__ */ diff --git a/drivers/misc/samsung/scsc/mif_reg.h b/drivers/misc/samsung/scsc/mif_reg.h deleted file mode 100755 index 785471bcc873..000000000000 --- a/drivers/misc/samsung/scsc/mif_reg.h +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIF_REG_H -#define __MIF_REG_H - -/*********************************/ -/* PLATFORM register definitions */ -/*********************************/ -#define NUM_MBOX_PLAT 8 -#define NUM_SEMAPHORE 12 - -#define MAILBOX_WLBT_BASE 0x0000 -#define MAILBOX_WLBT_REG(r) (MAILBOX_WLBT_BASE + (r)) -#define MCUCTRL 0x000 /* MCU Controller Register */ -/* R0 [31:16] - Int FROM R4/M4 */ -#define INTGR0 0x008 /* Interrupt Generation Register 0 (r/w) */ -#define INTCR0 0x00C /* Interrupt Clear Register 0 (w) */ -#define INTMR0 0x010 /* Interrupt Mask Register 0 (r/w) */ -#define INTSR0 0x014 /* Interrupt Status Register 0 (r) */ -#define INTMSR0 0x018 /* Interrupt Mask Status Register 0 (r) */ -/* R1 [15:0] - Int TO R4 */ -#define INTGR1 0x01c /* Interrupt Generation Register 1 */ -#define INTCR1 0x020 /* Interrupt Clear Register 1 */ -#define INTMR1 0x024 /* Interrupt Mask Register 1 */ -#define INTSR1 0x028 /* Interrupt Status Register 1 */ -#define INTMSR1 0x02c /* Interrupt Mask Status Register 1 */ -/* R2 [15:0] - Int TO M4 */ -#define INTGR2 0x030 /* Interrupt Generation Register 2 */ -#define INTCR2 0x034 /* Interrupt Clear Register 2 */ -#define INTMR2 0x038 /* Interrupt Mask Register 2 */ -#define INTSR2 0x03c /* Interrupt Status Register 2 */ -#define INTMSR2 0x040 /* Interrupt Mask Status Register 2 */ -#define MIF_INIT 0x04c /* MIF_init */ -#define IS_VERSION 0x050 /* Version Information Register */ -#define ISSR_BASE 0x080 /* IS_Shared_Register Base address */ -#define ISSR(r) (ISSR_BASE + (4 * (r))) -#define SEMAPHORE_BASE 0x180 /* IS_Shared_Register Base address */ -#define SEMAPHORE(r) (SEMAPHORE_BASE + (4 * (r))) -#define SEMA0CON 0x1c0 -#define SEMA0STATE 0x1c8 - - -/* POWER */ -/* Page 594 datasheet */ -/* Base Address - 0x11C8_0000 */ -#define WIFI_CTRL_NS 0x0140 /* WIFI Control SFR non-secure */ -#define WIFI_PWRON BIT(1) -#define WIFI_RESET_SET BIT(2) -#define WIFI_ACTIVE_EN BIT(5) /* Enable of WIFI_ACTIVE_REQ */ -#define WIFI_ACTIVE_CLR BIT(6) /* WIFI_ACTIVE_REQ is clear internally on WAKEUP */ -#define WIFI_RESET_REQ_EN BIT(7) /* 1:enable, 0:disable Enable of WIFI_RESET_REQ */ -#define WIFI_RESET_REQ_CLR BIT(8) /* WIFI_RESET_REQ is clear internally on WAKEUP */ -#define MASK_WIFI_PWRDN_DONE BIT(9) /* 1:mask, 0 : pass RTC clock out enable to WIFI - * This mask WIFI_PWRDN_DONE come in from WIFI. - * If MASK_WIFI_PWRDN_DONE = 1, WIFI enter to DOWN - * state without checking WIFI_PWRDN_DONE*/ - - - -#define WIFI_CTRL_S 0x0144 /* WIFI Control SFR secure */ -#define WIFI_START BIT(3) /* WIFI Reset release control If WIFI_START = 1, - * WIFI exit from DOWN state and go to UP state. - * If this field is set to high (WIFI_START = 1) - * WIFI state can go to UP state. This signal can be - * auto-clear by DIRECTWR at UP */ - -#define WIFI_STAT 0x0148 /* Indicate whether WIFI uses MIF domain */ -#define WIFI_DEBUG 0x014c /* MIF sleep, wakeup debugging control */ -/* Page 1574 datasheet */ -#define PMU_ALIVE_BASE 0x0000 -#define PMU_ALIVE_REG(r) (PMU_ALIVE_BASE + (r)) -#define WIFI2AP_MEM_CONFIG0 0x0150 /* Control WLBT_MEM_SIZE. */ -#define WLBT2AP_MIF_ACCESS_WIN0 0x0154 /* ACCESS_CONTROL_PERI_IP */ -#define WLBT2AP_MIF_ACCESS_WIN1 0x0158 /* ACCESS_CONTROL_PERI_IP */ -#define WLBT2AP_MIF_ACCESS_WIN2 0x015a /* ACCESS_CONTROL_PERI_IP */ -#define WLBT2AP_MIF_ACCESS_WIN3 0x0160 /* ACCESS_CONTROL_PERI_IP */ -#define WIFI2AP_MEM_CONFIG1 0x0164 /* Control WLBT_MEM_BA0 */ -#define WLBT_BOOT_TEST_RST_CFG 0x0168 /* WLBT_IRAM_BOOT_OFFSET */ - /* WLBT_IRAM_BOOT_TEST */ - /* WLBT2AP_PERI_PROT2 */ -#define WLBT2AP_PERI_ACCESS_WIN 0x016c /* WLBT2AP_PERI_ACCESS_END - WLBT2AP_PERI_ACCESS_START */ -#define WIFI2AP_MODAPIF_CONFIG 0x0170 /* WLBT2AP_PERI_ACCESS_END - WLBT2AP_PERI_ACCESS_START */ -#define WIFI2AP_QOS 0x0170 /* RT */ -#define WIFI2AP_MEM_CONFIG2 0x017c /* Control WLBT_MEM_BA1 */ -#define WIFI2AP_MEM_CONFIG3 0x0184 /* Control WLBT_ADDR_RNG */ - -/* Power down registers */ -#define RESET_ASB_WIFI_SYS_PWR_REG 0x11f4 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define TCXO_GATE_WIFI_SYS_PWR_REG 0x11f0 /* Control power state in LOWPWR mode 1 - on, 0 */ -#define LOGIC_RESET_WIFI_SYS_PWR_REG 0x11f8 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define CLEANY_BUS_WIFI_SYS_PWR_REG 0x11fc /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define CENTRAL_SEQ_WIFI_CONFIGURATION 0x0380 /* bit 16. Decides whether system-level low-power mode - * is used HIGH: System-level Low-Power mode - * disabled. LOW: System-level Low-Power mode - * enabled. When system enters low-power mode, - * this field is automatically cleared to HIGH. */ - -#define CENTRAL_SEQ_WIFI_STATUS 0x0384 /* 23:16 Check statemachine status */ -#define STATES 0xff0000 - -#define SYS_PWR_CFG BIT(0) -#define SYS_PWR_CFG_2 (BIT(0) | BIT(1)) -#define SYS_PWR_CFG_16 BIT(16) - - -/* CMU registers to request PLL for USB Clock */ -#define USBPLL_CON0 0x1000 -#define AP2WIFI_USBPLL_REQ BIT(0) /* 1: Request PLL, 0: Release PLL */ - -#define USBPLL_CON1 0x1004 /* */ -#define AP2WLBT_USBPLL_WPLL_SEL BIT(0) /* 1: WLBT, 0: AP */ -#define AP2WLBT_USBPLL_WPLL_EN BIT(1) /* 1: Enable, 0: Disable */ - -/***** Interrupts ******** - * - * - MBOX - * - WIFI_ACTIVE (pag 553) - * comes from BLK_WIFI. Initial value is low and then this value becomes high after WIFI booting. If - * some problem occurs within WIFI, WIFI_ACTIVE can be low by WIFI CPU. AP CPU detects that WIFI_ACTIVE is - * low after WIFI_ACTIVE is high. And WIFI_ACTIVE detected goes to GIC's interrupt source. At ISR, AP CPU - * makes wake source and interrupt clear as setting WIFI_CTRL__WIFI_ACTIVE_CLR. WIFI_ACTIVE_CLR is auto - * clear by direct-write function. - * - * - WIFI_RESET_REQ (pag 554) - * WIFI can request WIFI reset only by WIFI_RESET_REQ. If WIFI_RESET_REQ is asserted, AP PMU detects it as - * wakeup source and interrupt source. At ISR, AP CPU makes wakeup source clear as setting - * WIFI_CTRL__CP_RESET_REQ_CLR. But, interrupt can be not clear because the interrupt goes to GIC directly - * from WIFI. (It use make function within GIC) WIFI_RESET_REQ_CLR is auto clear by direct-write function. - */ - -#endif /* __MIF_REG_H */ diff --git a/drivers/misc/samsung/scsc/mif_reg_S5E3830.h b/drivers/misc/samsung/scsc/mif_reg_S5E3830.h deleted file mode 100644 index 0b12dbe65ed5..000000000000 --- a/drivers/misc/samsung/scsc/mif_reg_S5E3830.h +++ /dev/null @@ -1,222 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIF_REG_3830_H -#define __MIF_REG_3830_H - -/**************************************************************************** - * This header uses values from Nacho Exynos 3830 User Manual - * A copy can be found in http://cognidox/SC-508880-SP - ****************************************************************************/ - - -/*********************************/ -/* PLATFORM register definitions */ -/*********************************/ -#define NUM_MBOX_PLAT 8 -#define NUM_SEMAPHORE 12 - -#define MAILBOX_WLBT_BASE 0x0000 -#define MAILBOX_WLBT_REG(r) (MAILBOX_WLBT_BASE + (r)) -#define MCUCTRL 0x000 /* MCU Controller Register */ -/* R0 [31:16] - Int FROM R4/M4 */ -#define INTGR0 0x008 /* Interrupt Generation Register 0 (r/w) */ -#define INTCR0 0x00C /* Interrupt Clear Register 0 (w) */ -#define INTMR0 0x010 /* Interrupt Mask Register 0 (r/w) */ -#define INTSR0 0x014 /* Interrupt Status Register 0 (r) */ -#define INTMSR0 0x018 /* Interrupt Mask Status Register 0 (r) */ -/* R1 [15:0] - Int TO R4/M4 */ -#define INTGR1 0x01c /* Interrupt Generation Register 1 */ -#define INTCR1 0x020 /* Interrupt Clear Register 1 */ -#define INTMR1 0x024 /* Interrupt Mask Register 1 */ -#define INTSR1 0x028 /* Interrupt Status Register 1 */ -#define INTMSR1 0x02c /* Interrupt Mask Status Register 1 */ -#define MIF_INIT 0x04c /* MIF_init */ -#define IS_VERSION 0x050 /* Version Information Register */ -#define ISSR_BASE 0x080 /* IS_Shared_Register Base address */ -#define ISSR(r) (ISSR_BASE + (4 * (r))) -#define SEMAPHORE_BASE 0x180 /* IS_Shared_Register Base address */ -#define SEMAPHORE(r) (SEMAPHORE_BASE + (4 * (r))) -#define SEMA0CON 0x1c0 -#define SEMA0STATE 0x1c8 -#define SEMA1CON 0x1e0 -#define SEMA1STATE 0x1e8 - -#define WLBT_PBUS_BASE 0x14C00000 - -// CBUS : APM_BUS -// PBUS : CFG_BUS - -/* New WLBT SFRs for MEM config */ -#define WLBT_PBUS_D_TZPC_SFR (WLBT_PBUS_BASE + 0x10000) -#define WLBT_PBUS_BAAW_DBUS (WLBT_PBUS_BASE + 0x20000) -#define WLBT_PBUS_BAAW_CBUS (WLBT_PBUS_BASE + 0x30000) -#define WLBT_PBUS_SMAPPER (WLBT_PBUS_BASE + 0x40000) -#define WLBT_PBUS_SYSREG (WLBT_PBUS_BASE + 0x50000) -#define WLBT_PBUS_BOOT (WLBT_PBUS_BASE + 0x60000) - -#define VGPIO_TX_MONITOR 0x1700 -#define VGPIO_TX_MON_BIT29 BIT(29) - -/* Exynos 3830 UM - TODO */ -#define WLBT_CONFIGURATION 0x3100 -#define LOCAL_PWR_CFG BIT(0) /* Control power state 0: Power down 1: Power on */ - -/* Exynos 3830 UM - TODO */ -#define WLBT_STATUS 0x3104 -#define WLBT_STATUS_BIT0 BIT(0) /* Status 0 : Power down 1 : Power on */ - -/* Exynos 3830 UM - TODO */ -#define WLBT_STATES 0x3108 /* STATES [7:0] States index for debugging - * 0x00 : Reset - * 0x10 : Power up - * 0x80 : Power down - * */ -#define WLBT_OPTION 0x310C -#define WLBT_OPTION_DATA BIT(3) - -/* Exynos 3830 UM - TODO */ -#define WLBT_CTRL_NS 0x3110 /* WLBT Control SFR non-secure */ -#define WLBT_ACTIVE_CLR BIT(6) /* WLBT_ACTIVE_REQ is clear internally on WAKEUP */ -#define WLBT_ACTIVE_EN BIT(5) /* Enable of WIFI_ACTIVE_REQ */ - -/* Exynos 3830 UM - TODO */ -#define WLBT_CTRL_S 0x3114 /* WLBT Control SFR secure */ -#define WLBT_START BIT(3) /* CP control enable 0: Disable 1: Enable */ - -/* Exynos 3830 UM - TODO */ -#define WLBT_OUT 0x3120 -#define SWEEPER_BYPASS BIT(13) /* SWEEPER bypass mode control(WLBT2AP path) If - * this bit is set to 1, SWEEPER is bypass mode. - */ -#define SWEEPER_PND_CLR_REQ BIT(7) /* SWEEPER_CLEAN Request. SWPPER is the IP - * that can clean up hung transaction in the Long hop - * async Bus Interface, when get hung - * state. 0: Normal 1: SWEEPER CLEAN Requested - */ - -/* Exynos 3830 UM - Exynos3830_12_PMU.docx 1.10.566 */ -#define WLBT_IN 0x3124 -/* TODO: nacho does not have BUS_READY */ -#define BUS_READY BIT(4) /* BUS ready indication signal when reset released. 0: - * Normal 1: BUS ready state */ -#define PWRDOWN_IND BIT(2) /* PWRDOWN state indication 0: Normal 1: In the - * power down state */ -#define SWEEPER_PND_CLR_ACK BIT(0) /* SWEEPER_CLEAN ACK signal. SWPPER is the IP - * that can clean up hung transaction in the Long hop - * async Bus Interface, when get hung - * state. 0: Normal 1: SWEEPER CLEAN - * Acknowledged */ -/* Exynos 3830 UM - Exynos3830_12_PMU.docx Page 38 */ -#define WLBT_INT_EN 0x3144 -#define PWR_REQ_F BIT(3) -#define TCXO_REQ_F BIT(5) - -/* Exynos 3830 UM - TODO */ -#define WLBT_STAT 0x0058 -#define WLBT_PWRDN_DONE BIT(0) /* Check WLBT power-down status.*/ -#define WLBT_ACCESS_MIF BIT(4) /* Check whether WLBT accesses MIF domain */ - -/* Exynos 3830 UM - TODO */ -#define WLBT_DEBUG 0x005C - -/* Exynos 3830 UM - TODO */ -#define MIF_CTRL 0x3810 -#define TCXO_EN BIT(0) /* XCLKREQ enable 0: Disable 1: Enable */ - -/* Exynos 3830 UM - TODO */ -#define TOP_OUT 0x3920 -#define PWRRGTON_CP BIT(1) /* XPWRRTON_CP control 0: Disable 1: Enable */ - -/* Exynos 3830 UM - TODO */ -#define TCXO_BUF_CTRL 0x3B78 -#define TCXO_BUF_BIAS_EN_WLBT BIT(0) - -/* New WLBT SFRs for MEM config */ - -/* end address is exclusive so the ENDx register should be set to the first - * address that is not accessible through that BAAW. - * - * Another very important point to note here is we are using BAAW0 to expose - * 16MB region, so other BAAWs can be used for other purposes - */ -#define WLBT_DBUS_BAAW_0_START 0x80000000 // Start of DRAM for WLBT R7 -#define WLBT_DBUS_BAAW_0_END 0x81000000 // 16 MB -#define WLBT_DBUS_BAAW_1_START 0xC0000000 -#define WLBT_DBUS_BAAW_1_END 0xDFFFFFFF - -/* #define WLBT_DBUS_BAAW_2_START 0x80800000 -#define WLBT_DBUS_BAAW_2_END WLBT_DBUS_BAAW_3_START -#define WLBT_DBUS_BAAW_3_START 0x80C00000 -#define WLBT_DBUS_BAAW_3_END WLBT_DBUS_BAAW_4_START -#define WLBT_DBUS_BAAW_4_START 0x81000000 -#define WLBT_DBUS_BAAW_4_END 0x813FFFFF */ - -#define WLBT_BAAW_CON_INIT_DONE (1 << 31) -#define WLBT_BAAW_CON_EN_WRITE (1 << 1) -#define WLBT_BAAW_CON_EN_READ (1 << 0) -#define WLBT_BAAW_ACCESS_CTRL (WLBT_BAAW_CON_INIT_DONE | WLBT_BAAW_CON_EN_WRITE | WLBT_BAAW_CON_EN_READ) - -/* ref Confluence Maxwell152+Memory+Map */ -#define WLBT_CBUS_BAAW_0_START 0xA0000000 // CP2WLBT MBOX -#define WLBT_CBUS_BAAW_0_END 0xA000FFFF//WLBT_CBUS_BAAW_1_START -#define WLBT_CBUS_BAAW_1_START 0xA0010000 // MAILBOX_GNSS2WLBT -#define WLBT_CBUS_BAAW_1_END 0xA00CFFFF//WLBT_CBUS_BAAW_6_START // TODO -#define WLBT_CBUS_BAAW_2_START 0xA0020000 // MAILBOX_APM2WLBT -#define WLBT_CBUS_BAAW_2_END WLBT_CBUS_BAAW_3_START -#define WLBT_CBUS_BAAW_3_START 0xA0030000 // MAILBOX_AP2WLBT -#define WLBT_CBUS_BAAW_3_END WLBT_CBUS_BAAW_4_START -#define WLBT_CBUS_BAAW_4_START 0xA0040000 // MAILBOX_WLBT2ABOX -#define WLBT_CBUS_BAAW_4_END WLBT_CBUS_BAAW_5_START -#define WLBT_CBUS_BAAW_5_START 0xA0050000 // MAILBOX_WLBT2CHUB -#define WLBT_CBUS_BAAW_5_END WLBT_CBUS_BAAW_6_START -#define WLBT_CBUS_BAAW_6_START 0xA0060000 // GPIO_CMGP -#define WLBT_CBUS_BAAW_6_END WLBT_CBUS_BAAW_7_START -#define WLBT_CBUS_BAAW_7_START 0xA0070000 // ADC_CMGP_AP -#define WLBT_CBUS_BAAW_7_END WLBT_CBUS_BAAW_8_START -#define WLBT_CBUS_BAAW_8_START 0xA0080000 // ADC_CMGP_CP -#define WLBT_CBUS_BAAW_8_END WLBT_CBUS_BAAW_9_START -#define WLBT_CBUS_BAAW_9_START 0xA0090000 // SYSREG_CMGP2WLBT -#define WLBT_CBUS_BAAW_9_END WLBT_CBUS_BAAW_A_START -#define WLBT_CBUS_BAAW_A_START 0xA00A0000 // USI_CMGP00 -#define WLBT_CBUS_BAAW_A_END WLBT_CBUS_BAAW_B_START -#define WLBT_CBUS_BAAW_B_START 0xA00B0000 // reserved -#define WLBT_CBUS_BAAW_B_END WLBT_CBUS_BAAW_C_START -#define WLBT_CBUS_BAAW_C_START 0xA00C0000 // USI_CMGP01 -#define WLBT_CBUS_BAAW_C_END WLBT_CBUS_BAAW_D_START -#define WLBT_CBUS_BAAW_D_START 0xA00D0000 // CHUB_SRAM -#define WLBT_CBUS_BAAW_D_END 0xA010FFFF - -#define WLBT_PBUS_MBOX_CP2WLBT_BASE 0x11950000 -#define WLBT_PBUS_MBOX_GNSS2WLBT_BASE 0x119A0000 -#define WLBT_PBUS_MBOX_APM2WLBT_BASE 0x119B0000 -#define WLBT_PBUS_MBOX_AP2WLBT_BASE 0x119C0000 -#define WLBT_PBUS_MBOX_WLBT2ABOX_BASE 0x119D0000 -#define WLBT_PBUS_MBOX_WLBT2CHUB_BASE 0x119E0000 -#define WLBT_PBUS_GPIO_CMGP_BASE 0x11C30000 -#define WLBT_PBUS_ADC_CMGP_AP_BASE 0x11C40000 -#define WLBT_PBUS_ADC_CMGP_CP_BASE 0x11C50000 -#define WLBT_PBUS_SYSREG_CMGP2WLBT_BASE 0x11C60000 -#define WLBT_PBUS_USI_CMG00_BASE 0x11C70000 -#define WLBT_PBUS_USI_CMG01_BASE 0x11D20000 -#define WLBT_PBUS_CHUB_BASE 0x10E00000 /* TODO: confirm correct address */ - -/* EMA settings overloaded onto CHIP_VERSION_ID SFR - * (remap block) - */ -#define CHIP_VERSION_ID_VER_MASK 0xffc00000 /* [22:32] Version ID */ -#define CHIP_VERSION_ID_EMA_MASK 0x003fffff /* [0:21] EMA params */ -#define CHIP_VERSION_ID_EMA_VALUE (BIT(20) | \ - BIT(18) | \ - BIT(13) | \ - BIT(11) | \ - BIT(5) | \ - BIT(2) ) - -/* TZASC (TrustZone Address Space Controller) configuration for Katmai onwards */ -#define EXYNOS_SET_CONN_TZPC 0 -#define SMC_CMD_CONN_IF (0x82000710) -#endif /* __MIF_REG_3830_H */ diff --git a/drivers/misc/samsung/scsc/mif_reg_S5E7872.h b/drivers/misc/samsung/scsc/mif_reg_S5E7872.h deleted file mode 100755 index e1fb2a04d57b..000000000000 --- a/drivers/misc/samsung/scsc/mif_reg_S5E7872.h +++ /dev/null @@ -1,149 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIF_REG_7872_H -#define __MIF_REG_7872_H - -/*********************************/ -/* PLATFORM register definitions */ -/*********************************/ -#define NUM_MBOX_PLAT 8 -#define NUM_SEMAPHORE 12 - -#define MAILBOX_WLBT_BASE 0x0000 -#define MAILBOX_WLBT_REG(r) (MAILBOX_WLBT_BASE + (r)) -#define MCUCTRL 0x000 /* MCU Controller Register */ -/* R0 [31:16] - Int FROM R4/M4 */ -#define INTGR0 0x008 /* Interrupt Generation Register 0 (r/w) */ -#define INTCR0 0x00C /* Interrupt Clear Register 0 (w) */ -#define INTMR0 0x010 /* Interrupt Mask Register 0 (r/w) */ -#define INTSR0 0x014 /* Interrupt Status Register 0 (r) */ -#define INTMSR0 0x018 /* Interrupt Mask Status Register 0 (r) */ -/* R1 [15:0] - Int TO R4/M4 */ -#define INTGR1 0x01c /* Interrupt Generation Register 1 */ -#define INTCR1 0x020 /* Interrupt Clear Register 1 */ -#define INTMR1 0x024 /* Interrupt Mask Register 1 */ -#define INTSR1 0x028 /* Interrupt Status Register 1 */ -#define INTMSR1 0x02c /* Interrupt Mask Status Register 1 */ -#define MIF_INIT 0x04c /* MIF_init */ -#define IS_VERSION 0x050 /* Version Information Register */ -#define ISSR_BASE 0x080 /* IS_Shared_Register Base address */ -#define ISSR(r) (ISSR_BASE + (4 * (r))) -#define SEMAPHORE_BASE 0x180 /* IS_Shared_Register Base address */ -#define SEMAPHORE(r) (SEMAPHORE_BASE + (4 * (r))) -#define SEMA0CON 0x1c0 -#define SEMA0STATE 0x1c8 -#define SEMA1CON 0x1e0 -#define SEMA1STATE 0x1e8 - - -/* POWER */ -/* Page 594 datasheet */ -/* Base Address - 0x11C8_0000 */ -#define WIFI_CTRL_NS 0x0140 /* WIFI Control SFR non-secure */ -#define WIFI_PWRON BIT(1) -#define WIFI_RESET_SET BIT(2) -#define WIFI_ACTIVE_EN BIT(5) /* Enable of WIFI_ACTIVE_REQ */ -#define WIFI_ACTIVE_CLR BIT(6) /* WIFI_ACTIVE_REQ is clear internally on WAKEUP */ -#define WIFI_RESET_REQ_EN BIT(7) /* 1:enable, 0:disable Enable of WIFI_RESET_REQ */ -#define WIFI_RESET_REQ_CLR BIT(8) /* WIFI_RESET_REQ is clear internally on WAKEUP */ -#define MASK_WIFI_PWRDN_DONE BIT(9) /* 1:mask, 0 : pass RTC clock out enable to WIFI - * This mask WIFI_PWRDN_DONE come in from WIFI. - * If MASK_WIFI_PWRDN_DONE = 1, WIFI enter to DOWN - * state without checking WIFI_PWRDN_DONE*/ -#define RTC_OUT_EN BIT(10) /* 1:enable, 0 : disable This is enable signal on RTC - * CLK(32KHz). This clock can be used as WIFI PMU - * clock when WIFI is internal power-down and - * TCXO(26MHz) is disable at WIFI side.*/ -#define TCXO_ENABLE_SW BIT(11) /* 1:enable, 0 : disable This is enable signal on TCXO - * clock of WIFI. This signal can decide whether TCXO - * clock is active by software when WIFI is internal - * power-down or WIFI is in reset state at WIFI side. if - * this value is HIGH, TCXO is active regardless of - * hardware control */ -#define MASK_MIF_REQ BIT(12) /* 1:mask MIF_REQ comming from WIFI, 0 : disable */ -#define SET_SW_MIF_REQ BIT(13) /* MIF SLEEP control by SW 1: if MASK_MIF_REQ is - set to HIGH, MIF enters into down state by - SET_SW_MIF_REQ. */ -#define SWEEPER_BYPASS_DATA_EN BIT(16) /* CLEANY bypass mode control(WIFI2AP MEM path) - If this bit is set to 1, CLEANY in MIF block starts - operation. If this bit is set to 0, CLEANY is bypass - mode.*/ -#define SFR_SERIALIZER_DUR_DATA2REQ (BIT(20) | BIT(21)) /* Duration between DATA and REQUEST on - SFR_SERIALIZER */ - - -#define WIFI_CTRL_S 0x0144 /* WIFI Control SFR secure */ -#define WIFI_START BIT(3) /* WIFI Reset release control If WIFI_START = 1, - * WIFI exit from DOWN state and go to UP state. - * If this field is set to high (WIFI_START = 1) - * WIFI state can go to UP state. This signal can be - * auto-clear by DIRECTWR at UP */ - -#define WIFI_STAT 0x0148 -#define WIFI_PWRDN_DONE BIT(0) /* Check WIFI power-down status.*/ -#define WIFI_ACCESS_MIF BIT(4) /* Check whether WIFI accesses MIF doman */ - -#define WIFI_DEBUG 0x014c /* MIF sleep, wakeup debugging control */ -#define EN_MIF_REQ BIT(0) /* Control MIF_REQ through GPIO_ALIVE. */ -#define EN_WIFI_ACTIVE BIT(2) /* Control WIFI_ACTIVE through GPIO_ALIVE. */ -#define EN_MIF_RESET_REQ BIT(3) /* Control WIFI_RESET_REQ through GPIO_ALIVE. */ -#define MASK_CLKREQ_WIFI BIT(8) /* When this field is set to HIGH, ALIVE ignores - * CLKREQ from WIFI.*/ - -/* TODO: Might be 0x10480000 */ -#define PMU_ALIVE_BASE 0x0000 -#define PMU_ALIVE_REG(r) (PMU_ALIVE_BASE + (r)) -#define WIFI2AP_MEM_CONFIG0 0x7300 /* MEM_SIZE SECTION_0 */ -#define WIFI2AP_MEM_CONFIG1 0x7304 /* BASE ADDRESS SECTION 0*/ -#define WIFI2AP_MEM_CONFIG2 0x7300 /* MEM_SIZE SECTION_0 */ -#define WIFI2AP_MEM_CONFIG3 0x7304 /* BASE ADDRESS SECTION 1*/ -#define WIFI2AP_MEM_CONFIG4 0x7300 /* MEM_SIZE SECTION_1 */ -#define WIFI2AP_MEM_CONFIG5 0x7304 /* BASE ADDRESS SECTION 0*/ -#define WIFI2AP_MIF_ACCESS_WIN0 0x7318 /* ACCESS_CONTROL SFR*/ -#define WIFI2AP_MIF_ACCESS_WIN1 0x731c /* ACCESS_CONTROL SFR*/ -#define WIFI2AP_PERI0_ACCESS_WIN0 0x7320 /* ACCESS WINDOW PERI */ -#define WIFI2AP_PERI0_ACCESS_WIN1 0x7324 /* ACCESS WINDOW PERI */ -#define WIFI2AP_PERI0_ACCESS_WIN2 0x7328 /* ACCESS WINDOW PERI */ -#define WIFI2AP_PERI0_ACCESS_WIN3 0x732c /* ACCESS WINDOW PERI */ -#define WLBT_BOOT_TEST_RST_CFG 0x7330 /* WLBT_IRAM_BOOT_OFFSET */ - /* WLBT_IRAM_BOOT_TEST */ - /* WLBT2AP_PERI_PROT2 */ - -/* Power down registers */ -#define RESET_AHEAD_WIFI_PWR_REG 0x1360 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define CLEANY_BUS_WIFI_SYS_PWR_REG 0x1364 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define LOGIC_RESET_WIFI_SYS_PWR_REG 0x1368 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define TCXO_GATE_WIFI_SYS_PWR_REG 0x136c /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WIFI_DISABLE_ISO_SYS_PWR_REG 0x1370 /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WIFI_RESET_ISO_SYS_PWR_REG 0x1374 /* Control power state in LOWPWR mode 1 - on, 0 */ - -#define CENTRAL_SEQ_WIFI_CONFIGURATION 0x0380 /* bit 16. Decides whether system-level low-power mode - * is used HIGH: System-level Low-Power mode - * disabled. LOW: System-level Low-Power mode - * enabled. When system enters low-power mode, - * this field is automatically cleared to HIGH. */ - -#define CENTRAL_SEQ_WIFI_STATUS 0x0384 /* 23:16 Check statemachine status */ -#define STATES 0xff0000 - -#define SYS_PWR_CFG BIT(0) -#define SYS_PWR_CFG_2 (BIT(0) | BIT(1)) -#define SYS_PWR_CFG_16 BIT(16) - - -/* CMU registers to request PLL for USB Clock */ -#define USBPLL_CON0 0x0200 -#define AP2WIFI_USBPLL_REQ BIT(0) /* 1: Request PLL, 0: Release PLL */ - -#define USBPLL_CON1 0x0204 -#define AP2WLBT_USBPLL_WPLL_SEL BIT(0) /* 1: WLBT, 0: AP */ -#define AP2WLBT_USBPLL_WPLL_EN BIT(1) /* 1: Enable, 0: Disable */ - -/* TZASC configuration for Katmai onward */ -#define WLBT_TZASC 0 -#define EXYNOS_SMC_WLBT_TZASC_CMD 0x82000710 -#endif /* __MIF_REG_7872_H */ diff --git a/drivers/misc/samsung/scsc/mif_reg_S5E7885.h b/drivers/misc/samsung/scsc/mif_reg_S5E7885.h deleted file mode 100644 index 449967cec839..000000000000 --- a/drivers/misc/samsung/scsc/mif_reg_S5E7885.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIF_REG_7885_H -#define __MIF_REG_7885_H - -/*********************************/ -/* PLATFORM register definitions */ -/*********************************/ -#define NUM_MBOX_PLAT 8 -#define NUM_SEMAPHORE 12 - -#define MAILBOX_WLBT_BASE 0x0000 -#define MAILBOX_WLBT_REG(r) (MAILBOX_WLBT_BASE + (r)) -#define MCUCTRL 0x000 /* MCU Controller Register */ -/* R0 [31:16] - Int FROM R4/M4 */ -#define INTGR0 0x008 /* Interrupt Generation Register 0 (r/w) */ -#define INTCR0 0x00C /* Interrupt Clear Register 0 (w) */ -#define INTMR0 0x010 /* Interrupt Mask Register 0 (r/w) */ -#define INTSR0 0x014 /* Interrupt Status Register 0 (r) */ -#define INTMSR0 0x018 /* Interrupt Mask Status Register 0 (r) */ -/* R1 [15:0] - Int TO R4/M4 */ -#define INTGR1 0x01c /* Interrupt Generation Register 1 */ -#define INTCR1 0x020 /* Interrupt Clear Register 1 */ -#define INTMR1 0x024 /* Interrupt Mask Register 1 */ -#define INTSR1 0x028 /* Interrupt Status Register 1 */ -#define INTMSR1 0x02c /* Interrupt Mask Status Register 1 */ -#define MIF_INIT 0x04c /* MIF_init */ -#define IS_VERSION 0x050 /* Version Information Register */ -#define ISSR_BASE 0x080 /* IS_Shared_Register Base address */ -#define ISSR(r) (ISSR_BASE + (4 * (r))) -#define SEMAPHORE_BASE 0x180 /* IS_Shared_Register Base address */ -#define SEMAPHORE(r) (SEMAPHORE_BASE + (4 * (r))) -#define SEMA0CON 0x1c0 -#define SEMA0STATE 0x1c8 -#define SEMA1CON 0x1e0 -#define SEMA1STATE 0x1e8 - - -/* POWER */ -/* Page 1173 datasheet */ -/* Base Address - 0x11C8_0000 */ -#define WIFI_CTRL_NS 0x0140 /* WIFI Control SFR non-secure */ -#define WIFI_PWRON BIT(1) -#define WIFI_RESET_SET BIT(2) -#define WIFI_ACTIVE_EN BIT(5) /* Enable of WIFI_ACTIVE_REQ */ -#define WIFI_ACTIVE_CLR BIT(6) /* WIFI_ACTIVE_REQ is clear internally on WAKEUP */ -#define WIFI_RESET_REQ_EN BIT(7) /* 1:enable, 0:disable Enable of WIFI_RESET_REQ */ -#define WIFI_RESET_REQ_CLR BIT(8) /* WIFI_RESET_REQ is clear internally on WAKEUP */ -#define MASK_WIFI_PWRDN_DONE BIT(9) /* 1:mask, 0 : pass RTC clock out enable to WIFI - * This mask WIFI_PWRDN_DONE come in from WIFI. - * If MASK_WIFI_PWRDN_DONE = 1, WIFI enter to DOWN - * state without checking WIFI_PWRDN_DONE*/ -#define RTC_OUT_EN BIT(10) /* 1:enable, 0 : disable This is enable signal on RTC - * CLK(32KHz). This clock can be used as WIFI PMU - * clock when WIFI is internal power-down and - * TCXO(26MHz) is disable at WIFI side.*/ -#define TCXO_ENABLE_SW BIT(11) /* 1:enable, 0 : disable This is enable signal on TCXO - * clock of WIFI. This signal can decide whether TCXO - * clock is active by software when WIFI is internal - * power-down or WIFI is in reset state at WIFI side. if - * this value is HIGH, TCXO is active regardless of - * hardware control */ -#define MASK_MIF_REQ BIT(12) /* 1:mask MIF_REQ comming from WIFI, 0 : disable */ -#define SET_SW_MIF_REQ BIT(13) /* MIF SLEEP control by SW 1: if MASK_MIF_REQ is - set to HIGH, MIF enters into down state by - SET_SW_MIF_REQ. */ -#define SWEEPER_BYPASS_DATA_EN BIT(16) /* CLEANY bypass mode control(WIFI2AP MEM path) - If this bit is set to 1, CLEANY in MIF block starts - operation. If this bit is set to 0, CLEANY is bypass - mode.*/ -#define SFR_SERIALIZER_DUR_DATA2REQ (BIT(20) | BIT(21)) /* Duration between DATA and REQUEST on - SFR_SERIALIZER */ - - -#define WIFI_CTRL_S 0x0144 /* WIFI Control SFR secure */ -#define WIFI_START BIT(3) /* WIFI Reset release control If WIFI_START = 1, - * WIFI exit from DOWN state and go to UP state. - * If this field is set to high (WIFI_START = 1) - * WIFI state can go to UP state. This signal can be - * auto-clear by DIRECTWR at UP */ - -#define WIFI_STAT 0x0148 -#define WIFI_PWRDN_DONE BIT(0) /* Check WIFI power-down status.*/ -#define WIFI_ACCESS_MIF BIT(4) /* Check whether WIFI accesses MIF doman */ - -#define WIFI_DEBUG 0x014c /* MIF sleep, wakeup debugging control */ -#define EN_MIF_REQ BIT(0) /* Control MIF_REQ through GPIO_ALIVE. */ -#define EN_WIFI_ACTIVE BIT(2) /* Control WIFI_ACTIVE through GPIO_ALIVE. */ -#define EN_MIF_RESET_REQ BIT(3) /* Control WIFI_RESET_REQ through GPIO_ALIVE. */ -#define MASK_CLKREQ_WIFI BIT(8) /* When this field is set to HIGH, ALIVE ignores - * CLKREQ from WIFI.*/ - -/* TODO: Might be 0x10480000 */ -#define PMU_ALIVE_BASE 0x0000 -#define PMU_ALIVE_REG(r) (PMU_ALIVE_BASE + (r)) -#define WIFI2AP_MEM_CONFIG0 0x7300 /* MEM_SIZE SECTION_0 */ -#define WIFI2AP_MEM_CONFIG1 0x7304 /* BASE ADDRESS SECTION 0*/ -#define WIFI2AP_MEM_CONFIG2 0x7300 /* MEM_SIZE SECTION_0 */ -#define WIFI2AP_MEM_CONFIG3 0x7304 /* BASE ADDRESS SECTION 1*/ -#define WIFI2AP_MEM_CONFIG4 0x7300 /* MEM_SIZE SECTION_1 */ -#define WIFI2AP_MEM_CONFIG5 0x7304 /* BASE ADDRESS SECTION 0*/ -#define WIFI2AP_MIF_ACCESS_WIN0 0x7318 /* ACCESS_CONTROL SFR*/ -#define WIFI2AP_MIF_ACCESS_WIN1 0x731c /* ACCESS_CONTROL SFR*/ -#define WIFI2AP_PERI0_ACCESS_WIN0 0x7320 /* ACCESS WINDOW PERI */ -#define WIFI2AP_PERI0_ACCESS_WIN1 0x7324 /* ACCESS WINDOW PERI */ -#define WIFI2AP_PERI0_ACCESS_WIN2 0x7328 /* ACCESS WINDOW PERI */ -#define WIFI2AP_PERI0_ACCESS_WIN3 0x732c /* ACCESS WINDOW PERI */ -#define WLBT_BOOT_TEST_RST_CFG 0x7330 /* WLBT_IRAM_BOOT_OFFSET */ - /* WLBT_IRAM_BOOT_TEST */ - /* WLBT2AP_PERI_PROT2 */ - -/* Power down registers */ -#define RESET_AHEAD_WIFI_PWR_REG 0x1360 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define CLEANY_BUS_WIFI_SYS_PWR_REG 0x1364 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define LOGIC_RESET_WIFI_SYS_PWR_REG 0x1368 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define TCXO_GATE_WIFI_SYS_PWR_REG 0x136c /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WIFI_DISABLE_ISO_SYS_PWR_REG 0x1370 /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WIFI_RESET_ISO_SYS_PWR_REG 0x1374 /* Control power state in LOWPWR mode 1 - on, 0 */ - -#define CENTRAL_SEQ_WIFI_CONFIGURATION 0x0380 /* bit 16. Decides whether system-level low-power mode - * is used HIGH: System-level Low-Power mode - * disabled. LOW: System-level Low-Power mode - * enabled. When system enters low-power mode, - * this field is automatically cleared to HIGH. */ - -#define CENTRAL_SEQ_WIFI_STATUS 0x0384 /* 23:16 Check statemachine status */ -#define STATES 0xff0000 - -#define SYS_PWR_CFG BIT(0) -#define SYS_PWR_CFG_2 (BIT(0) | BIT(1)) -#define SYS_PWR_CFG_16 BIT(16) - -/* TZASC configuration for Katmai onward */ -#define WLBT_TZASC 0 -#define EXYNOS_SMC_WLBT_TZASC_CMD 0x82000710 -#endif /* __MIF_REG_7885_H */ diff --git a/drivers/misc/samsung/scsc/mif_reg_S5E9610.h b/drivers/misc/samsung/scsc/mif_reg_S5E9610.h deleted file mode 100644 index 49120eb08e00..000000000000 --- a/drivers/misc/samsung/scsc/mif_reg_S5E9610.h +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIF_REG_9610_H -#define __MIF_REG_9610_H - -/*********************************/ -/* PLATFORM register definitions */ -/*********************************/ -#define NUM_MBOX_PLAT 8 -#define NUM_SEMAPHORE 12 - -#define MAILBOX_WLBT_BASE 0x0000 -#define MAILBOX_WLBT_REG(r) (MAILBOX_WLBT_BASE + (r)) -#define MCUCTRL 0x000 /* MCU Controller Register */ -/* R0 [31:16] - Int FROM R4/M4 */ -#define INTGR0 0x008 /* Interrupt Generation Register 0 (r/w) */ -#define INTCR0 0x00C /* Interrupt Clear Register 0 (w) */ -#define INTMR0 0x010 /* Interrupt Mask Register 0 (r/w) */ -#define INTSR0 0x014 /* Interrupt Status Register 0 (r) */ -#define INTMSR0 0x018 /* Interrupt Mask Status Register 0 (r) */ -/* R1 [15:0] - Int TO R4/M4 */ -#define INTGR1 0x01c /* Interrupt Generation Register 1 */ -#define INTCR1 0x020 /* Interrupt Clear Register 1 */ -#define INTMR1 0x024 /* Interrupt Mask Register 1 */ -#define INTSR1 0x028 /* Interrupt Status Register 1 */ -#define INTMSR1 0x02c /* Interrupt Mask Status Register 1 */ -#define MIF_INIT 0x04c /* MIF_init */ -#define IS_VERSION 0x050 /* Version Information Register */ -#define ISSR_BASE 0x080 /* IS_Shared_Register Base address */ -#define ISSR(r) (ISSR_BASE + (4 * (r))) -#define SEMAPHORE_BASE 0x180 /* IS_Shared_Register Base address */ -#define SEMAPHORE(r) (SEMAPHORE_BASE + (4 * (r))) -#define SEMA0CON 0x1c0 -#define SEMA0STATE 0x1c8 -#define SEMA1CON 0x1e0 -#define SEMA1STATE 0x1e8 - -/* POWER */ -/* Exynos 9610 UM - 9.9.1.16 */ -#define WLBT_CTRL_NS 0x0050 /* WLBT Control SFR non-secure */ - -#define WLBT_PWRON BIT(1) -#define WLBT_RESET_SET BIT(0) /* WLBT reset assertion control by using - * PMU_ALIVE_WLBT. - * 0x1: Reset Assertion, - * 0x0: Reset Release - */ -#define WLBT_ACTIVE_EN BIT(5) /* Enable of WIFI_ACTIVE_REQ */ -#define WLBT_ACTIVE_CLR BIT(6) /* WLBT_ACTIVE_REQ is clear internally on WAKEUP */ -#define WLBT_RESET_REQ_EN BIT(7) /* 1:enable, 0:disable Enable of WLBT_RESET_REQ */ -#define WLBT_RESET_REQ_CLR BIT(8) /* WLBT_RESET_REQ is clear internally on WAKEUP */ -#define MASK_PWR_REQ BIT(18) /* 1:mask PWR_REQ coming from WLBT, 0 : disable */ -#define MASK_TCXO_REQ BIT(20) /* 1:mask TCXO_REQ coming from CP, - * 0:enable request source - */ - -#define RTC_OUT_EN BIT(10) /* 1:enable, 0 : disable This is enable signal on RTC - * CLK(32KHz). This clock can be used as WLBT PMU - * clock when WLBT is internal power-down and - * TCXO(26MHz) is disable at WLBT side. - */ -#define TCXO_ENABLE_SW BIT(11) /* 1:enable, 0 : disable This is enable signal on TCXO - * clock of WLBT. This signal can decide whether TCXO - * clock is active by software when WLBT is internal - * power-down or WLBT is in reset state at WLBT side. if - * this value is HIGH, TCXO is active regardless of - * hardware control - */ -#define MASK_MIF_REQ BIT(12) /* 1:mask MIF_REQ coming from WLBT, 0 : disable */ -#define SET_SW_MIF_REQ BIT(13) /* MIF SLEEP control by SW 1: if MASK_MIF_REQ is - * set to HIGH, MIF enters into down state by - * SET_SW_MIF_REQ. - */ -#define SWEEPER_BYPASS_DATA_EN BIT(16) /* SWEEPER bypass mode control(WLBT2AP path) If - * this bit is set to 1, SWEEPER is bypass mode. - */ - -#define WLBT_CTRL_S 0x0054 /* WLBT Control SFR secure */ -#define WLBT_START BIT(0) /* WLBT initial Reset release control - * If CP_START = 1, PMU_RESET_SEQUENCER_CP - * starts initial reset release sequence - * and goes to UP state. - */ - -#define WLBT_STAT 0x0058 -#define WLBT_PWRDN_DONE BIT(0) /* Check WLBT power-down status.*/ -#define WLBT_ACCESS_MIF BIT(4) /* Check whether WLBT accesses MIF doman */ - -#define WLBT_DEBUG 0x005c /* MIF sleep, wakeup debugging control */ -#define EN_MIF_REQ BIT(0) /* Control MIF_REQ through GPIO_ALIVE. */ -#define EN_WLBT_ACTIVE BIT(2) /* Control WLBT_ACTIVE through GPIO_ALIVE. */ -#define EN_WLBT_RESET_REQ BIT(3) /* Control WLBT_RESET_REQ through GPIO_ALIVE. */ -#define MASK_CLKREQ_WLBT BIT(8) /* When this field is set to HIGH, ALIVE ignores - * CLKREQ from WLBT. - */ - -/* New WLBT SFRs for MEM config */ - -/* end address is exclusive so the ENDx register should be set to the first - * address that is not accessible through that BAAW. - * - * Another very important point to note here is we are using BAAW0 to expose - * 16MB region, so other BAAWs can be used for other purposes - */ -#define WLBT_DBUS_BAAW_0_START 0x80000000 -#define WLBT_DBUS_BAAW_0_END WLBT_DBUS_BAAW_4_START -#define WLBT_DBUS_BAAW_1_START 0x80400000 -#define WLBT_DBUS_BAAW_1_END WLBT_DBUS_BAAW_2_START -#define WLBT_DBUS_BAAW_2_START 0x80800000 -#define WLBT_DBUS_BAAW_2_END WLBT_DBUS_BAAW_3_START -#define WLBT_DBUS_BAAW_3_START 0x80C00000 -#define WLBT_DBUS_BAAW_3_END WLBT_DBUS_BAAW_4_START -#define WLBT_DBUS_BAAW_4_START 0x81000000 -#define WLBT_DBUS_BAAW_4_END 0x81400000 - -#define WLBT_BAAW_CON_INIT_DONE (1 << 31) -#define WLBT_BAAW_CON_EN_WRITE (1 << 1) -#define WLBT_BAAW_CON_EN_READ (1 << 0) -#define WLBT_BAAW_ACCESS_CTRL (WLBT_BAAW_CON_INIT_DONE | WLBT_BAAW_CON_EN_WRITE | WLBT_BAAW_CON_EN_READ) - -#define WLBT_PBUS_BAAW_0_START 0xA0000000 -#define WLBT_PBUS_BAAW_0_END WLBT_PBUS_BAAW_1_START -#define WLBT_PBUS_BAAW_1_START 0xA0010000 -#define WLBT_PBUS_BAAW_1_END WLBT_PBUS_BAAW_2_START -#define WLBT_PBUS_BAAW_2_START 0xA0060000 -#define WLBT_PBUS_BAAW_2_END WLBT_PBUS_BAAW_3_START -#define WLBT_PBUS_BAAW_3_START 0xA0100000 -#define WLBT_PBUS_BAAW_3_END WLBT_PBUS_BAAW_4_START -#define WLBT_PBUS_BAAW_4_START 0xA0110000 -#define WLBT_PBUS_BAAW_4_END WLBT_PBUS_BAAW_5_START -#define WLBT_PBUS_BAAW_5_START 0xA0120000 -#define WLBT_PBUS_BAAW_5_END 0xA0160000 - -#define WLBT_PBUS_MBOX_CP2WLBT_BASE 0x11950000//0xA0000000 -#define WLBT_PBUS_MBOX_SHUB2WLBT_BASE 0x119A0000//0xA0010000 -#define WLBT_PBUS_USI_CMG00_BASE 0x11D00000//0xA0060000 -#define WLBT_PBUS_SYSREG_CMGP2WLBT_BASE 0x11C80000//0xA0100000 -#define WLBT_PBUS_GPIO_CMGP_BASE 0x11C20000//0xA0110000 -#define WLBT_PBUS_SHUB_BASE 0x11200000//0xA0120000 - -/* EMA settings overloaded onto CHIP_VERSION_ID SFR - * (remap block) - */ -#define CHIP_VERSION_ID_VER_MASK 0xffc00000 /* [22:32] Version ID */ -#define CHIP_VERSION_ID_EMA_MASK 0x003fffff /* [0:21] EMA params */ -#define CHIP_VERSION_ID_EMA_VALUE (BIT(20) | \ - BIT(18) | \ - BIT(13) | \ - BIT(11) | \ - BIT(5) | \ - BIT(2) ) - -/* Power down registers */ -#define RESET_AHEAD_WLBT_SYS_PWR_REG 0x1360 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define CLEANY_BUS_WLBT_SYS_PWR_REG 0x1364 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define LOGIC_RESET_WLBT_SYS_PWR_REG 0x1368 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define TCXO_GATE_WLBT_SYS_PWR_REG 0x136C /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WLBT_DISABLE_ISO_SYS_PWR_REG 0x1370 /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WLBT_RESET_ISO_SYS_PWR_REG 0x1374 /* Control power state in LOWPWR mode 1 - on, 0 */ - -#define CENTRAL_SEQ_WLBT_CONFIGURATION 0x0180 /* bit 16. Decides whether system-level low-power mode - * is used HIGH: System-level Low-Power mode - * disabled. LOW: System-level Low-Power mode - * enabled. When system enters low-power mode, - * this field is automatically cleared to HIGH. - */ - -#define CENTRAL_SEQ_WLBT_STATUS 0x0184 /* 23:16 Check statemachine status */ -#define STATES 0xff0000 - -#define SYS_PWR_CFG BIT(0) -#define SYS_PWR_CFG_2 (BIT(0) | BIT(1)) -#define SYS_PWR_CFG_16 BIT(16) - -/* TZASC (TrustZone Address Space Controller) configuration for Katmai onwards */ -#define EXYNOS_SET_CONN_TZPC 0 -//#define SMC_CMD_CONN_IF 0x82000710 -#endif /* __MIF_REG_9610_H */ diff --git a/drivers/misc/samsung/scsc/mif_reg_S5E9630.h b/drivers/misc/samsung/scsc/mif_reg_S5E9630.h deleted file mode 100644 index eb5258610298..000000000000 --- a/drivers/misc/samsung/scsc/mif_reg_S5E9630.h +++ /dev/null @@ -1,327 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIF_REG_9630_H -#define __MIF_REG_9630_H - -/*********************************/ -/* PLATFORM register definitions */ -/*********************************/ -#define NUM_MBOX_PLAT 8 -#define NUM_SEMAPHORE 12 - -#define MAILBOX_WLBT_BASE 0x0000 -#define MAILBOX_WLBT_REG(r) (MAILBOX_WLBT_BASE + (r)) -#define MCUCTRL 0x000 /* MCU Controller Register */ -/* R0 [31:16] - Int FROM R4/M4 */ -#define INTGR0 0x008 /* Interrupt Generation Register 0 (r/w) */ -#define INTCR0 0x00C /* Interrupt Clear Register 0 (w) */ -#define INTMR0 0x010 /* Interrupt Mask Register 0 (r/w) */ -#define INTSR0 0x014 /* Interrupt Status Register 0 (r) */ -#define INTMSR0 0x018 /* Interrupt Mask Status Register 0 (r) */ -/* R1 [15:0] - Int TO R4/M4 */ -#define INTGR1 0x01c /* Interrupt Generation Register 1 */ -#define INTCR1 0x020 /* Interrupt Clear Register 1 */ -#define INTMR1 0x024 /* Interrupt Mask Register 1 */ -#define INTSR1 0x028 /* Interrupt Status Register 1 */ -#define INTMSR1 0x02c /* Interrupt Mask Status Register 1 */ -#define MIF_INIT 0x04c /* MIF_init */ -#define IS_VERSION 0x050 /* Version Information Register */ -#define ISSR_BASE 0x080 /* IS_Shared_Register Base address */ -#define ISSR(r) (ISSR_BASE + (4 * (r))) -#define SEMAPHORE_BASE 0x180 /* IS_Shared_Register Base address */ -#define SEMAPHORE(r) (SEMAPHORE_BASE + (4 * (r))) -#define SEMA0CON 0x1c0 -#define SEMA0STATE 0x1c8 -#define SEMA1CON 0x1e0 -#define SEMA1STATE 0x1e8 - -#define WLBT_PBUS_BASE 0x14400000 - -// CBUS : APM_BUS -// PBUS : CFG_BUS - -/* New WLBT SFRs for MEM config */ -#define WLBT_PBUS_D_TZPC_SFR (WLBT_PBUS_BASE + 0x10000) -#define WLBT_PBUS_BAAW_DBUS (WLBT_PBUS_BASE + 0x20000) -#define WLBT_PBUS_BAAW_CBUS (WLBT_PBUS_BASE + 0x30000) -#define WLBT_PBUS_SMAPPER (WLBT_PBUS_BASE + 0x40000) -#define WLBT_PBUS_SYSREG (WLBT_PBUS_BASE + 0x50000) -#define WLBT_PBUS_BOOT (WLBT_PBUS_BASE + 0x60000) - -#define TZPC_PROT0STAT 0x14410200 -#define TZPC_PROT0SET 0x14410204 - -/* POWER */ - -#define VGPIO_TX_MONITOR 0x1700 -#define VGPIO_TX_MON_BIT29 BIT(29) - -/* Exynos 9630 UM - 9.8.719 */ -#define WLBT_CONFIGURATION 0x3300 -#define LOCAL_PWR_CFG BIT(0) /* Control power state 0: Power down 1: Power on */ - -/* Exynos 9630 UM - 9.8.720 */ -#define WLBT_STATUS 0x3304 -#define WLBT_STATUS_BIT0 BIT(0) /* Status 0 : Power down 1 : Power on */ - -/* Exynos 9630 UM - 9.8.721 */ -#define WLBT_STATES 0x3308 /* STATES [7:0] States index for debugging - * 0x00 : Reset - * 0x10 : Power up - * 0x80 : Power down - * */ - -/* Exynos 9630 UM - 9.8.722 */ -#define WLBT_OPTION 0x330C -#define WLBT_OPTION_DATA BIT(3) - -/* Exynos 9630 UM - 9.8.723 */ -#define WLBT_CTRL_NS 0x3310 /* WLBT Control SFR non-secure */ -#define WLBT_ACTIVE_CLR BIT(8) /* WLBT_ACTIVE_REQ is clear internally on WAKEUP */ -#define WLBT_ACTIVE_EN BIT(7) /* Enable of WIFI_ACTIVE_REQ */ -#define SW_TCXO_REQ BIT(6) /* SW TCXO Request register, if MASK_TCXO_REQ - * filed value is 1, This register value control TCXO Request*/ -#define MASK_TCXO_REQ BIT(5) /* 1:mask TCXO_REQ coming from CP, - * 0:enable request source - */ -#define TCXO_GATE BIT(4) /* TCXO gate control 0: TCXO enabled 1: TCXO gated */ -/*#define SET_SW_MIF_REQ BIT(13)*/ /* MIF SLEEP control by SW 1: if MASK_MIF_REQ is - * set to HIGH, MIF enters into down state by - * SET_SW_MIF_REQ. - */ -/*#define MASK_MIF_REQ BIT(12)*/ /* 1:mask MIF_REQ coming from WLBT, 0 : disable */ -/*#define RTC_OUT_EN BIT(10)*/ /* 1:enable, 0 : disable This is enable signal on RTC - * CLK(32KHz). This clock can be used as WLBT PMU - * clock when WLBT is internal power-down and - * TCXO(26MHz) is disable at WLBT side. - */ - - -/*------------------------------------*/ - -//??????#define WLBT_PWRON BIT(1) -#define WLBT_RESET_SET BIT(0) /* WLBT reset assertion control by using - * PMU_ALIVE_WLBT. - * 0x1: Reset Assertion, - * 0x0: Reset Release - */ -#define WLBT_RESET_REQ_EN BIT(7) /* 1:enable, 0:disable Enable of WLBT_RESET_REQ */ -#define WLBT_RESET_REQ_CLR BIT(8) /* WLBT_RESET_REQ is clear internally on WAKEUP */ -#define MASK_PWR_REQ BIT(1) /* 1:mask PWR_REQ coming from WLBT, 0 : disable */ -#define TCXO_ENABLE_SW BIT(1) /* 1:enable, 0 : disable This is enable signal on TCXO - * clock of WLBT. This signal can decide whether TCXO - * clock is active by software when WLBT is internal - * power-down or WLBT is in reset state at WLBT side. if - * this value is HIGH, TCXO is active regardless of - * hardware control - */ -/* from wlbt_if_S5E7920.h excite code */ - -/* PMU_ALIVE Bit Field */ -/* WLBT_CTRL_NS */ -//#define CLEANY_BYPASS_DATA_EN BIT(16) -//#define SET_SW_MIF_REQ BIT(13) -//#define MASK_MIF_REQ BIT(12) -//#define RTC_OUT_EN BIT(10) -//#define MASK_WLBT_PWRDN_DONE BIT(9) -//#define WLBT_RESET_REQ_CLR BIT(8) -//#define WLBT_RESET_REQ_EN BIT(7) -//#define WLBT_ACTIVE_CLR BIT(6) -//#define WLBT_ACTIVE_EN BIT(5) -//#define WLBT_RESET_SET BIT(0) -//#define WLBT_PWRON BIT(1) - -/* WLBT_CTRL_S */ -//#define WLBT_START BIT(0) - -/* WLBT_STAT */ -//#define WLBT_ACCESS_MIF BIT(4) -//#define WLBT_PWRDN_DONE BIT(0) - -/* WLBT_DEBUG */ -//#define MASK_CLKREQ_WLBT BIT(8) -//#define EN_PWR_REQ BIT(5) -//#define EN_WLBT_WAKEUP_REQ BIT(4) -//#define EN_WLBT_RESET_REQ BIT(3) -//#define EN_WLBT_ACTIVE BIT(2) -//#define EN_MIF_REQ BIT(0) - -/* WLBT_BOOT_TEST_RST_CONFIG */ -#define WLBT_IRAM_BOOT_OFFSET (BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8)) -#define WLBT_IRAM_BOOT_TEST BIT(5) -#define WLBT_NOREMAP_BOOT_TEST BIT(4) -#define WLBT2AP_PERI_PROT2 BIT(2) - -/* WLBT_QOS */ -#define WLBT_AWQOS (BIT(19) | BIT(18) | BIT(17) | BIT(16)) -#define WLBT_ARQOS (BIT(11) | BIT(10) | BIT(9) | BIT(8)) -#define WLBT_QOS_OVERRIDE BIT(0) - -/*------------------------------------*/ - -/* Exynos 9630 UM - 9.8.724 */ -#define WLBT_CTRL_S 0x3314 /* WLBT Control SFR secure */ -#define WLBT_START BIT(3) /* CP control enable 0: Disable 1: Enable */ - -/* Exynos 9630 UM - 9.8.725 */ -#define WLBT_OUT 0x3320 -#define SWEEPER_BYPASS BIT(13) /* SWEEPER bypass mode control(WLBT2AP path) If - * this bit is set to 1, SWEEPER is bypass mode. - */ -#define SWEEPER_PND_CLR_REQ BIT(7) /* SWEEPER_CLEAN Request. SWPPER is the IP - * that can clean up hung transaction in the Long hop - * async Bus Interface, when get hung - * state. 0: Normal 1: SWEEPER CLEAN Requested - */ - -/* Exynos 9630 UM - 9.8.726 */ -#define WLBT_IN 0x3324 -#define BUS_READY BIT(4) /* BUS ready indication signal when reset released. 0: - * Normal 1: BUS ready state */ -#define PWRDOWN_IND BIT(2) /* PWRDOWN state indication 0: Normal 1: In the - * power down state */ -#define SWEEPER_PND_CLR_ACK BIT(0) /* SWEEPER_CLEAN ACK signal. SWPPER is the IP - * that can clean up hung transaction in the Long hop - * async Bus Interface, when get hung - * state. 0: Normal 1: SWEEPER CLEAN - * Acknowledged */ -/* Exynos 9630 UM - 9.8.728 */ -#define WLBT_INT_EN 0x3344 -#define PWR_REQ_F BIT(3) -#define TCXO_REQ_F BIT(5) - -/* Exynos 9630 UM - 9.8.10 */ -#define WLBT_STAT 0x0058 -#define WLBT_PWRDN_DONE BIT(0) /* Check WLBT power-down status.*/ -#define WLBT_ACCESS_MIF BIT(4) /* Check whether WLBT accesses MIF domain */ - -/* Exynos 9630 UM - 9.8.11 */ -#define WLBT_DEBUG 0x005C /* MIF sleep, wakeup debugging control */ -/* need to find where have they moved */ -//#define EN_MIF_REQ BIT(0) /* Control MIF_REQ through GPIO_ALIVE. */ -//#define EN_WLBT_ACTIVE BIT(2) /* Control WLBT_ACTIVE through GPIO_ALIVE. */ -//#define EN_WLBT_RESET_REQ BIT(3) /* Control WLBT_RESET_REQ through GPIO_ALIVE. */ -#define MASK_CLKREQ_WLBT BIT(8) /* When this field is set to HIGH, ALIVE ignores - * CLKREQ from WLBT. - */ - -#define RESET_SEQUENCER_STATUS 0x0504 -#define RESET_STATUS_MASK (BIT(10)|BIT(9)|BIT(8)) -#define RESET_STATUS (5 << 8) - -#define PMU_SHARED_PWR_REQ_WLBT_CONTROL_STATUS 0x8008 -#define CTRL_STATUS_MASK 0x1 - -#define CLEANY_BUS_WLBT_CONFIGURATION 0x3b20 -#define CLEANY_CFG_MASK 0x1 - -#define CLEANY_BUS_WLBT_STATUS 0x3B24 -#define CLEANY_STATUS_MASK (BIT(17)|BIT(16)) - -/* Exynos 9630 UM - 9.8.763 */ -#define SYSTEM_OUT 0x3A20 -#define PWRRGTON_CON BIT(9) /* XPWRRTON_CON control 0: Disable 1: Enable */ - -/* Exynos 9630 UM - 9.8.812 */ -#define TCXO_BUF_CTRL 0x3C10 -#define TCXO_BUF_BIAS_EN_WLBT BIT(2) -#define TCXO_BUF_EN_WLBT BIT(3) - -/* New WLBT SFRs for MEM config */ - -/* end address is exclusive so the ENDx register should be set to the first - * address that is not accessible through that BAAW. - * - * Another very important point to note here is we are using BAAW0 to expose - * 16MB region, so other BAAWs can be used for other purposes - */ -#define WLBT_DBUS_BAAW_0_START 0x80000000 // Start of DRAM for WLBT R7 -#define WLBT_DBUS_BAAW_0_END WLBT_DBUS_BAAW_4_START // 16 MB -#define WLBT_DBUS_BAAW_1_START 0x80400000 -#define WLBT_DBUS_BAAW_1_END WLBT_DBUS_BAAW_2_START -#define WLBT_DBUS_BAAW_2_START 0x80800000 -#define WLBT_DBUS_BAAW_2_END WLBT_DBUS_BAAW_3_START -#define WLBT_DBUS_BAAW_3_START 0x80C00000 -#define WLBT_DBUS_BAAW_3_END WLBT_DBUS_BAAW_4_START -#define WLBT_DBUS_BAAW_4_START 0x81000000 -#define WLBT_DBUS_BAAW_4_END 0x813FFFFF - -#define WLBT_BAAW_CON_INIT_DONE (1 << 31) -#define WLBT_BAAW_CON_EN_WRITE (1 << 1) -#define WLBT_BAAW_CON_EN_READ (1 << 0) -#define WLBT_BAAW_ACCESS_CTRL (WLBT_BAAW_CON_INIT_DONE | WLBT_BAAW_CON_EN_WRITE | WLBT_BAAW_CON_EN_READ) - -/* ref Confluence Maxwell450+Memory+Map */ -#define WLBT_CBUS_BAAW_0_START 0xA0000000 // CP2WLBT MBOX -#define WLBT_CBUS_BAAW_0_END 0xA000FFFF - -#define WLBT_CBUS_BAAW_1_START 0xA0010000 // GNSS,APM,AP,ABOX,CHUB2WLBT MBOX -#define WLBT_CBUS_BAAW_1_END 0xA005FFFF - -#define WLBT_CBUS_BAAW_2_START 0xA0060000 // CMGP SFR GPIO_CMGP_BASE -#define WLBT_CBUS_BAAW_2_END 0xA009FFFF - -#define WLBT_CBUS_BAAW_3_START 0xA00A0000 // CMGP SFR SYSREG_CMGP2WLBT_BASE -#define WLBT_CBUS_BAAW_3_END 0xA00CFFFF - -#define WLBT_CBUS_BAAW_4_START 0xA00D0000 // CMGP SFR USI_CMG00_BASE -#define WLBT_CBUS_BAAW_4_END 0xA015FFFF - -#define WLBT_CBUS_BAAW_5_START 0xA0160000 // CHUB SFR CHUB_USICHUB0_BASE -#define WLBT_CBUS_BAAW_5_END 0xA01BFFFF - -#define WLBT_CBUS_BAAW_6_START 0xA01C0000 // CHUB SFR CHUB_BASE -#define WLBT_CBUS_BAAW_6_END 0xA01EFFFF - -#define WLBT_PBUS_MBOX_CP2WLBT_BASE 0x10F50000 -#define WLBT_PBUS_MBOX_GNSS2WLBT_BASE 0x10FA0000 -#define WLBT_PBUS_MBOX_SHUB2WLBT_BASE 0x119A0000 -#define WLBT_PBUS_USI_CMG00_BASE 0x11500000 -#define WLBT_PBUS_SYSREG_CMGP2WLBT_BASE 0x11490000 -#define WLBT_PBUS_GPIO_CMGP_BASE 0x11430000 -#define WLBT_PBUS_CHUB_USICHUB0_BASE 0x11B70000 -#define WLBT_PBUS_CHUB_BASE 0x11A00000 - - - -/* CHIP_VERSION_ID SFR (remap block) 0x14450410 - */ -#define CHIP_VERSION_ID_OFFSET 0x410 -#define CHIP_VERSION_ID_VER_MASK 0xFFFFFFFF /* [00:31] Version ID */ -#define CHIP_VERSION_ID_IP_PMU 0x0000F000 /* [12:15] PMU ROM Rev */ -#define CHIP_VERSION_ID_IP_MINOR 0x000F0000 /* [16:19] Minor Rev */ -#define CHIP_VERSION_ID_IP_MAJOR 0x00F00000 /* [20:23] Major Rev */ -#define CHIP_VERSION_ID_IP_PMU_SHIFT 12 -#define CHIP_VERSION_ID_IP_MINOR_SHIFT 16 -#define CHIP_VERSION_ID_IP_MAJOR_SHIFT 20 - -/* Power down registers */ -#define RESET_AHEAD_WLBT_SYS_PWR_REG 0x1360 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define CLEANY_BUS_WLBT_SYS_PWR_REG 0x1364 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define LOGIC_RESET_WLBT_SYS_PWR_REG 0x1368 /* Control power state in LOWPWR mode 1 - on, 0 - down*/ -#define TCXO_GATE_WLBT_SYS_PWR_REG 0x136C /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WLBT_DISABLE_ISO_SYS_PWR_REG 0x1370 /* Control power state in LOWPWR mode 1 - on, 0 */ -#define WLBT_RESET_ISO_SYS_PWR_REG 0x1374 /* Control power state in LOWPWR mode 1 - on, 0 */ - -#define CENTRAL_SEQ_WLBT_CONFIGURATION 0x0180 /* bit 16. Decides whether system-level low-power mode - * is used HIGH: System-level Low-Power mode - * disabled. LOW: System-level Low-Power mode - * enabled. When system enters low-power mode, - * this field is automatically cleared to HIGH. - */ - -//#define CENTRAL_SEQ_WLBT_STATUS 0x0184 /* 23:16 Check statemachine status */ -//#define STATES 0xff0000 - -#define SYS_PWR_CFG BIT(0) -#define SYS_PWR_CFG_2 (BIT(0) | BIT(1)) -#define SYS_PWR_CFG_16 BIT(16) - -/* TZASC (TrustZone Address Space Controller) configuration for Katmai onwards */ -#define EXYNOS_SET_CONN_TZPC 0 -#define SMC_CMD_CONN_IF (0x82000710) -#endif /* __MIF_REG_9630_H */ diff --git a/drivers/misc/samsung/scsc/mif_reg_smapper.h b/drivers/misc/samsung/scsc/mif_reg_smapper.h deleted file mode 100755 index 3a2294f20194..000000000000 --- a/drivers/misc/samsung/scsc/mif_reg_smapper.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIF_REG_SMAPPER_H -#define __MIF_REG_SMAPPER_H - -/***************************************/ -/* SMAPPER v2.0.1 register definitions */ -/***************************************/ -#define NUM_BANKS_160 4 -#define NUM_BANKS_64 7 -#define NUM_BANKS (NUM_BANKS_160 + NUM_BANKS_64) - -/* It enables CP_ADDR_MAP */ -#define ADDR_MAP_EN_BASE 0x000 -#define ADDR_MAP_EN(b) (ADDR_MAP_EN_BASE + (0x10 * (b))) - -/* SRAM write control. Set this register before CP initializes SRAM. - * If disable this bit, CP cannot acces SRAM by APB I/F. You need to - * disable ADDR_MAP_CTRL before you set this bit 1'b1 means - * SRAM write, 1'b0 means SRAM read - */ -#define SRAM_WRITE_CTRL_BASE 0x004 -#define SRAM_WRITE_CTRL(b) (SRAM_WRITE_CTRL_BASE + (0x10 * (b))) - -/* It defines the start address of CP virtual addres for 0-31. You - * need to disable ADDR_MAP_EN before you set this bit - */ -#define START_ADDR_BASE 0x008 -#define START_ADDR(b) (START_ADDR_BASE + (0x10 * (b))) - -/* For CP_ADDR_GRANULARITY between 0-31. You - * need to disable ADDR_MAP_EN before you set this bit - */ -#define ADDR_GRANULARITY_BASE 0x00c -#define ADDR_GRANULARITY(b) (ADDR_GRANULARITY_BASE + (0x10 * (b))) - -/* It defines the MSB part of 36-bit AP phys address [35:0]. It is starting - * point of access permission. - */ -#define AW_START_ADDR 0x100 -/* It defines the MSB part of 36-bit AP phys address [35:0]. It is end - * point of access permission. - */ -#define AW_END_ADDR 0x104 -/* It defines out-of-bound of access windows when it is set to 1'b1 by - * Access Window - */ -#define AW_ADDR_MAP_STATUS 0x200 -#define ORIGIN_ADDR_AR 0x204 -#define ORIGIN_ADDR_AW 0x208 -/* Read APB bus errors */ -#define APB_STATUS_0 0x300 -#define APB_STATUS_1 0x304 - -/* The Q-channel interfaces enable communication to an external - * power controller - */ -#define SMAPPER_QCH_DISABLE 0x400 - -/* SRAM r/w addres - * PWDATA[24:0] is used for 25'b SRAM read/write. - * Only can access ADDR_MAP_EN is disabled - */ -#define SRAM_BANK_BASE 0x1000 - -#define SRAM_BANK_INDEX(b, r) ((SRAM_BANK_BASE + (b * 0x400)) + (4 * (r))) - -#define ADDR_MAP_EN_BIT BIT(0) - -#endif /*_MIF_REG_SMAPPER_H*/ diff --git a/drivers/misc/samsung/scsc/mifintrbit.c b/drivers/misc/samsung/scsc/mifintrbit.c deleted file mode 100644 index fb6a55447b5c..000000000000 --- a/drivers/misc/samsung/scsc/mifintrbit.c +++ /dev/null @@ -1,263 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Uses */ -#include -#include -#include -#include -#include "scsc_mif_abs.h" - -/* Implements */ -#include "mifintrbit.h" - -/* default handler just logs a warning and clears the bit */ -static void mifintrbit_default_handler(int irq, void *data) -{ - struct mifintrbit *intr = (struct mifintrbit *)data; - unsigned long flags; - - spin_lock_irqsave(&intr->spinlock, flags); - intr->mif->irq_bit_clear(intr->mif, irq); - spin_unlock_irqrestore(&intr->spinlock, flags); -} - -static void print_bitmaps(struct mifintrbit *intr) -{ - unsigned long dst1, dst2, dst3; - - bitmap_copy_le(&dst1, intr->bitmap_tohost, MIFINTRBIT_NUM_INT); - bitmap_copy_le(&dst2, intr->bitmap_fromhost_r4, MIFINTRBIT_NUM_INT); - bitmap_copy_le(&dst3, intr->bitmap_fromhost_m4, MIFINTRBIT_NUM_INT); -} - -static void mifiintrman_isr(int irq, void *data) -{ - struct mifintrbit *intr = (struct mifintrbit *)data; - unsigned long flags; - unsigned long int irq_reg = 0; - int bit; - - /* Avoid unused parameter error */ - (void)irq; - - spin_lock_irqsave(&intr->spinlock, flags); - irq_reg = intr->mif->irq_get(intr->mif); - - print_bitmaps(intr); - for_each_set_bit(bit, &irq_reg, MIFINTRBIT_NUM_INT) { - if (intr->mifintrbit_irq_handler[bit] != mifintrbit_default_handler) - intr->mifintrbit_irq_handler[bit](bit, intr->irq_data[bit]); - } - - spin_unlock_irqrestore(&intr->spinlock, flags); -} - -/* Public functions */ -int mifintrbit_alloc_tohost(struct mifintrbit *intr, mifintrbit_handler handler, void *data) -{ - struct scsc_mif_abs *mif; - unsigned long flags; - int which_bit = 0; - - spin_lock_irqsave(&intr->spinlock, flags); - - /* Search for free slots */ - which_bit = find_first_zero_bit(intr->bitmap_tohost, MIFINTRBIT_NUM_INT); - - if (which_bit >= MIFINTRBIT_NUM_INT) - goto error; - - if (intr->mifintrbit_irq_handler[which_bit] != mifintrbit_default_handler) { - spin_unlock_irqrestore(&intr->spinlock, flags); - goto error; - } - - /* Get abs implementation */ - mif = intr->mif; - - /* Mask to prevent spurious incoming interrupts */ - mif->irq_bit_mask(mif, which_bit); - /* Clear the interrupt */ - mif->irq_bit_clear(mif, which_bit); - - /* Register the handler */ - intr->mifintrbit_irq_handler[which_bit] = handler; - intr->irq_data[which_bit] = data; - - /* Once registration is set, and IRQ has been cleared, unmask the interrupt */ - mif->irq_bit_unmask(mif, which_bit); - - /* Update bit mask */ - set_bit(which_bit, intr->bitmap_tohost); - - spin_unlock_irqrestore(&intr->spinlock, flags); - - return which_bit; - -error: - spin_unlock_irqrestore(&intr->spinlock, flags); - SCSC_TAG_ERR(MIF, "Error registering irq\n"); - return -EIO; -} - -int mifintrbit_free_tohost(struct mifintrbit *intr, int which_bit) -{ - struct scsc_mif_abs *mif; - unsigned long flags; - - if (which_bit >= MIFINTRBIT_NUM_INT) - goto error; - - spin_lock_irqsave(&intr->spinlock, flags); - /* Get abs implementation */ - mif = intr->mif; - - /* Mask to prevent spurious incoming interrupts */ - mif->irq_bit_mask(mif, which_bit); - /* Set the handler with default */ - intr->mifintrbit_irq_handler[which_bit] = mifintrbit_default_handler; - intr->irq_data[which_bit] = NULL; - /* Clear the interrupt for hygiene */ - mif->irq_bit_clear(mif, which_bit); - /* Update bit mask */ - clear_bit(which_bit, intr->bitmap_tohost); - spin_unlock_irqrestore(&intr->spinlock, flags); - - return 0; - -error: - SCSC_TAG_ERR(MIF, "Error unregistering irq\n"); - return -EIO; -} - -int mifintrbit_alloc_fromhost(struct mifintrbit *intr, enum scsc_mif_abs_target target) -{ - unsigned long flags; - int which_bit = 0; - unsigned long *p; - - - spin_lock_irqsave(&intr->spinlock, flags); - - if (target == SCSC_MIF_ABS_TARGET_R4) - p = intr->bitmap_fromhost_r4; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - else if (target == SCSC_MIF_ABS_TARGET_M4) - p = intr->bitmap_fromhost_r4; - else if (target == SCSC_MIF_ABS_TARGET_M4_1) - p = intr->bitmap_fromhost_r4; -#else - else if (target == SCSC_MIF_ABS_TARGET_M4) - p = intr->bitmap_fromhost_m4; -#endif - else - goto error; - - /* Search for free slots */ - which_bit = find_first_zero_bit(p, MIFINTRBIT_NUM_INT); - - if (which_bit == MIFINTRBIT_NUM_INT) - goto error; - - /* Update bit mask */ - set_bit(which_bit, p); - - spin_unlock_irqrestore(&intr->spinlock, flags); - - return which_bit; -error: - spin_unlock_irqrestore(&intr->spinlock, flags); - SCSC_TAG_ERR(MIF, "Error allocating bit %d on %s\n", - which_bit, target ? "M4" : "R4"); - return -EIO; -} - -int mifintrbit_free_fromhost(struct mifintrbit *intr, int which_bit, enum scsc_mif_abs_target target) -{ - unsigned long flags; - unsigned long *p; - - spin_lock_irqsave(&intr->spinlock, flags); - - if (which_bit >= MIFINTRBIT_NUM_INT) - goto error; - - if (target == SCSC_MIF_ABS_TARGET_R4) - p = intr->bitmap_fromhost_r4; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - else if (target == SCSC_MIF_ABS_TARGET_M4) - p = intr->bitmap_fromhost_r4; - else if (target == SCSC_MIF_ABS_TARGET_M4_1) - p = intr->bitmap_fromhost_r4; -#else - else if (target == SCSC_MIF_ABS_TARGET_M4) - p = intr->bitmap_fromhost_m4; -#endif - else - goto error; - - /* Clear bit mask */ - clear_bit(which_bit, p); - spin_unlock_irqrestore(&intr->spinlock, flags); - - return 0; -error: - spin_unlock_irqrestore(&intr->spinlock, flags); - SCSC_TAG_ERR(MIF, "Error freeing bit %d on %s\n", - which_bit, target ? "M4" : "R4"); - return -EIO; -} - -/* core API */ -void mifintrbit_deinit(struct mifintrbit *intr) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&intr->spinlock, flags); - /* Set all handlers to default before unregistering the handler */ - for (i = 0; i < MIFINTRBIT_NUM_INT; i++) - intr->mifintrbit_irq_handler[i] = mifintrbit_default_handler; - intr->mif->irq_unreg_handler(intr->mif); - spin_unlock_irqrestore(&intr->spinlock, flags); -} - -void mifintrbit_init(struct mifintrbit *intr, struct scsc_mif_abs *mif) -{ - int i; - - spin_lock_init(&intr->spinlock); - /* Set all handlersd to default before hooking the hardware interrupt */ - for (i = 0; i < MIFINTRBIT_NUM_INT; i++) - intr->mifintrbit_irq_handler[i] = mifintrbit_default_handler; - - /* reset bitmaps */ - bitmap_zero(intr->bitmap_tohost, MIFINTRBIT_NUM_INT); - bitmap_zero(intr->bitmap_fromhost_r4, MIFINTRBIT_NUM_INT); - bitmap_zero(intr->bitmap_fromhost_m4, MIFINTRBIT_NUM_INT); - - /** - * Pre-allocate/reserve MIF interrupt bits 0 in both - * .._fromhost_r4 and .._fromhost_m4 interrupt bits. - * - * These bits are used for purpose of forcing Panics from - * either MX manager or GDB monitor channels. - */ - set_bit(MIFINTRBIT_RESERVED_PANIC_R4, intr->bitmap_fromhost_r4); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - set_bit(MIFINTRBIT_RESERVED_PANIC_M4, intr->bitmap_fromhost_m4); - set_bit(MIFINTRBIT_RESERVED_PANIC_M4_1, intr->bitmap_fromhost_m4_1); -#else - set_bit(MIFINTRBIT_RESERVED_PANIC_M4, intr->bitmap_fromhost_m4); -#endif - - /* register isr with mif abstraction */ - mif->irq_reg_handler(mif, mifiintrman_isr, (void *)intr); - - /* cache mif */ - intr->mif = mif; -} diff --git a/drivers/misc/samsung/scsc/mifintrbit.h b/drivers/misc/samsung/scsc/mifintrbit.h deleted file mode 100644 index d8019736dcbf..000000000000 --- a/drivers/misc/samsung/scsc/mifintrbit.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIFINTRBIT_H -#define __MIFINTRBIT_H - -#include - -/** MIF Interrupt Bit Handler prototype. */ -typedef void (*mifintrbit_handler)(int which_bit, void *data); - -struct mifintrbit; /* fwd - opaque pointer */ - -#define MIFINTRBIT_NUM_INT 16 - -/** Reserve MIF interrupt bits 0 in the to-r4 and to-m4 registers for purpose of forcing panics */ -#define MIFINTRBIT_RESERVED_PANIC_R4 0 -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT -#define MIFINTRBIT_RESERVED_PANIC_M4 0 -#define MIFINTRBIT_RESERVED_PANIC_M4_1 0 -#else -#define MIFINTRBIT_RESERVED_PANIC_M4 0 -#endif - -void mifintrbit_init(struct mifintrbit *intr, struct scsc_mif_abs *mif); -void mifintrbit_deinit(struct mifintrbit *intr); - -/** Allocates TOHOST MIF interrupt bits, and associates handler for the AP bit. - * Returns the bit index.*/ -int mifintrbit_alloc_tohost(struct mifintrbit *intr, mifintrbit_handler handler, void *data); -/** Deallocates TOHOST MIF interrupt bits */ -int mifintrbit_free_tohost(struct mifintrbit *intr, int which_bit); -/* Get an interrupt bit associated with the target (R4/M4) -FROMHOST direction - * Function returns the IRQ bit associated , -EIO if error */ -int mifintrbit_alloc_fromhost(struct mifintrbit *intr, enum scsc_mif_abs_target target); -/* Free an interrupt bit associated with the target (R4/M4) -FROMHOST direction - * Function returns the 0 if succedes , -EIO if error */ -int mifintrbit_free_fromhost(struct mifintrbit *intr, int which_bit, enum scsc_mif_abs_target target); - - -struct mifintrbit { - void(*mifintrbit_irq_handler[MIFINTRBIT_NUM_INT]) (int irq, void *data); - void *irq_data[MIFINTRBIT_NUM_INT]; - struct scsc_mif_abs *mif; - /* Use spinlock is it may be in IRQ context */ - spinlock_t spinlock; - /* Interrupt allocation bitmaps */ - DECLARE_BITMAP(bitmap_tohost, MIFINTRBIT_NUM_INT); - DECLARE_BITMAP(bitmap_fromhost_r4, MIFINTRBIT_NUM_INT); - DECLARE_BITMAP(bitmap_fromhost_m4, MIFINTRBIT_NUM_INT); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - DECLARE_BITMAP(bitmap_fromhost_m4_1, MIFINTRBIT_NUM_INT); -#endif -}; - - -#endif diff --git a/drivers/misc/samsung/scsc/mifmboxman.c b/drivers/misc/samsung/scsc/mifmboxman.c deleted file mode 100644 index 7d18555a71a9..000000000000 --- a/drivers/misc/samsung/scsc/mifmboxman.c +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* uses */ -#include -#include -#include -#include -#include -#include "scsc_mif_abs.h" - -/* Implements */ -#include "mifmboxman.h" - -int mifmboxman_init(struct mifmboxman *mbox) -{ - if (mbox->in_use) - return -EBUSY; - - mutex_init(&mbox->lock); - mbox->mbox_free = MIFMBOX_NUM; - mbox->in_use = true; - bitmap_zero(mbox->bitmap, MIFMBOX_NUM); - - return 0; -} - -bool mifmboxman_alloc_mboxes(struct mifmboxman *mbox, int n, int *first_mbox_index) -{ - unsigned int index = 0; - unsigned int available; - u8 i; - - mutex_lock(&mbox->lock); - - if ((n > MIFMBOX_NUM) || (n == 0) || !mbox->in_use) - goto error; - - while (index <= (MIFMBOX_NUM - n)) { - available = 0; - - /* Search consecutive blocks */ - for (i = 0; i < n; i++) { - if (test_bit((i + index), mbox->bitmap)) - break; - available++; - } - - if (available == n) { - *first_mbox_index = index; - - for (i = 0; i < n; i++) - set_bit(index++, mbox->bitmap); - - mbox->mbox_free -= n; - goto exit; - } else - index = index + available + 1; - } -error: - SCSC_TAG_ERR(MIF, "Error allocating mbox\n"); - mutex_unlock(&mbox->lock); - return false; -exit: - mutex_unlock(&mbox->lock); - return true; - -} - -void mifmboxman_free_mboxes(struct mifmboxman *mbox, int first_mbox_index, int n) -{ - int index = 0; - int total_free = 0; - - mutex_lock(&mbox->lock); - if ((n > MIFMBOX_NUM) || - ((n + first_mbox_index) > MIFMBOX_NUM) || - (n == 0) || - !mbox->in_use) - goto error; - - for (index = first_mbox_index; index < (first_mbox_index + n); index++) - if (test_bit(index, mbox->bitmap)) { - clear_bit(index, mbox->bitmap); - total_free++; - } - - mbox->mbox_free += total_free; - mutex_unlock(&mbox->lock); - return; -error: - SCSC_TAG_ERR(MIF, "Error freeing mbox\n"); - mutex_unlock(&mbox->lock); -} - -u32 *mifmboxman_get_mbox_ptr(struct mifmboxman *mbox, struct scsc_mif_abs *mif_abs, int mbox_index) -{ - /* Avoid unused parameter error */ - (void)mbox; - - return mif_abs->get_mbox_ptr(mif_abs, mbox_index); -} - - -int mifmboxman_deinit(struct mifmboxman *mbox) -{ - mutex_lock(&mbox->lock); - if (!mbox->in_use) - return -ENODEV; - mbox->in_use = false; - mutex_unlock(&mbox->lock); - return 0; -} diff --git a/drivers/misc/samsung/scsc/mifmboxman.h b/drivers/misc/samsung/scsc/mifmboxman.h deleted file mode 100644 index 81f3da96937a..000000000000 --- a/drivers/misc/samsung/scsc/mifmboxman.h +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIFMBOXMAN_H -#define __MIFMBOXMAN_H - -#include - -/* TODO: Needs to define the max mem */ - -struct mifmboxman; -struct scsc_mif_abs; -struct mutex; - -int mifmboxman_init(struct mifmboxman *mbox); -bool mifmboxman_alloc_mboxes(struct mifmboxman *mbox, int n, int *first_mbox_index); -void mifmboxman_free_mboxes(struct mifmboxman *mbox, int first_mbox_index, int n); -u32 *mifmboxman_get_mbox_ptr(struct mifmboxman *mbox, struct scsc_mif_abs *mif_abs, int mbox_index); -int mifmboxman_deinit(struct mifmboxman *mbox); - -#ifdef CONFIG_SOC_EXYNOS7570 -#define MIFMBOX_NUM 8 -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) || defined(CONFIG_SOC_EXYNOS9610) -#define MIFMBOX_NUM 4 -#else /* emulation */ -#define MIFMBOX_NUM 8 -#endif - -/* Inclusion in core.c treat it as opaque */ -struct mifmboxman { - bool in_use; - u32 mbox_free; - DECLARE_BITMAP(bitmap, MIFMBOX_NUM); - struct mutex lock; -}; -#endif diff --git a/drivers/misc/samsung/scsc/mifproc.c b/drivers/misc/samsung/scsc/mifproc.c deleted file mode 100644 index c162accc18d3..000000000000 --- a/drivers/misc/samsung/scsc/mifproc.c +++ /dev/null @@ -1,519 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include "mifproc.h" -#include "scsc_mif_abs.h" -#include "miframman.h" - -#define MX_MAX_PROC_RAMMAN 2 /* Number of RAMMANs to track */ - -static struct proc_dir_entry *procfs_dir; -static struct proc_dir_entry *procfs_dir_ramman[MX_MAX_PROC_RAMMAN]; - -/* WARNING --- SINGLETON FOR THE TIME BEING */ -/* EXTEND PROC ENTRIES IF NEEDED!!!!! */ -struct scsc_mif_abs *mif_global; - -static int mifprocfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = MIF_PDE_DATA(inode); - return 0; -} - -MIF_PROCFS_RW_FILE_OPS(mif_dump); -MIF_PROCFS_RW_FILE_OPS(mif_writemem); -MIF_PROCFS_RW_FILE_OPS(mif_reg); - -/* miframman ops */ -MIF_PROCFS_RO_FILE_OPS(ramman_total); -MIF_PROCFS_RO_FILE_OPS(ramman_offset); -MIF_PROCFS_RO_FILE_OPS(ramman_start); -MIF_PROCFS_RO_FILE_OPS(ramman_free); -MIF_PROCFS_RO_FILE_OPS(ramman_used); -MIF_PROCFS_RO_FILE_OPS(ramman_size); - -MIF_PROCFS_SEQ_FILE_OPS(ramman_list); - -static ssize_t mifprocfs_mif_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - /* Avoid unused parameter error */ - (void)file; - - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "OK"); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - - -static ssize_t mifprocfs_mif_writemem_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - /* Avoid unused parameter error */ - (void)file; - - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "OK"); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t mifprocfs_mif_dump_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - /* Avoid unused parameter error */ - (void)file; - - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "OK"); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t mifprocfs_mif_writemem_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - char *sptr, *token; - unsigned int len = 0, pass = 0; - u32 value = 0, address = 0; - int match = 0; - void *mem; - - /* Avoid unused parameter error */ - (void)file; - (void)ppos; - - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - sptr = buf; - - while ((token = strsep(&sptr, " ")) != NULL) { - switch (pass) { - /* register */ - case 0: - if ((token[0] == '0') && (token[1] == 'x')) { - if (kstrtou32(token, 16, &address)) { - SCSC_TAG_INFO(MIF, "Wrong format:
\n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 0xcafecafe\"\n"); - goto error; - } - } else { - SCSC_TAG_INFO(MIF, "Wrong format:
\n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 0xcafecafe\"\n"); - goto error; - } - break; - /* value */ - case 1: - if ((token[0] == '0') && (token[1] == 'x')) { - if (kstrtou32(token, 16, &value)) { - SCSC_TAG_INFO(MIF, "Wrong format:
\n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 0xcafecafe\"\n"); - goto error; - } - } else { - SCSC_TAG_INFO(MIF, "Wrong format:
\n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 0xcafecafe\"\n"); - goto error; - } - break; - } - pass++; - } - if (pass != 2 && !match) { - SCSC_TAG_INFO(MIF, "Wrong format:
\n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 0xcafecafe\"\n"); - goto error; - } - - /* Get memory offset */ - mem = mif_global->get_mifram_ptr(mif_global, 0); - if (!mem) { - SCSC_TAG_INFO(MIF, "Mem not allocated\n"); - goto error; - } - - SCSC_TAG_INFO(MIF, "Setting value 0x%x at address 0x%x offset\n", value, address); - - - *((u32 *)(mem + address)) = value; -error: - return count; -} - -static ssize_t mifprocfs_mif_dump_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - char *sptr, *token; - unsigned int len = 0, pass = 0; - u32 address = 0; - u32 size; - u8 unit; - void *mem; - - (void)file; - (void)ppos; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - sptr = buf; - - while ((token = strsep(&sptr, " ")) != NULL) { - switch (pass) { - /* address */ - case 0: - if ((token[0] == '0') && (token[1] == 'x')) { - if (kstrtou32(token, 16, &address)) { - SCSC_TAG_INFO(MIF, "Incorrect format,,,address should start by 0x\n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 256 8\"\n"); - goto error; - } - SCSC_TAG_INFO(MIF, "address %d 0x%x\n", address, address); - } else { - SCSC_TAG_INFO(MIF, "Incorrect format,,,address should start by 0x\n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 256 8\"\n"); - goto error; - } - break; - /* size */ - case 1: - if (kstrtou32(token, 0, &size)) { - SCSC_TAG_INFO(MIF, "Incorrect format,,, for size\n"); - goto error; - } - SCSC_TAG_INFO(MIF, "size: %d\n", size); - break; - - /* unit */ - case 2: - if (kstrtou8(token, 0, &unit)) { - SCSC_TAG_INFO(MIF, "Incorrect format,,, for unit\n"); - goto error; - } - if ((unit != 8) && (unit != 16) && (unit != 32)) { - SCSC_TAG_INFO(MIF, "Unit %d should be 8/16/32\n", unit); - goto error; - } - SCSC_TAG_INFO(MIF, "unit: %d\n", unit); - break; - } - pass++; - } - if (pass != 3) { - SCSC_TAG_INFO(MIF, "Wrong format: \n"); - SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 256 8\"\n"); - goto error; - } - - mem = mif_global->get_mifram_ptr(mif_global, 0); - if (!mem) { - SCSC_TAG_INFO(MIF, "Mem not allocated\n"); - goto error; - } - - /* Add offset */ - mem = mem + address; - - SCSC_TAG_INFO(MIF, "Phy addr :%p ref addr :%x\n", mem, address); - SCSC_TAG_INFO(MIF, "------------------------------------------------------------------------\n"); - print_hex_dump(KERN_WARNING, "ref addr offset: ", DUMP_PREFIX_OFFSET, 16, unit/8, mem, size, 1); - SCSC_TAG_INFO(MIF, "------------------------------------------------------------------------\n"); -error: - return count; -} - -static ssize_t mifprocfs_mif_reg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - void *mem; - - if (!mif_global) { - SCSC_TAG_INFO(MIF, "Endpoint not registered\n"); - return 0; - } - - mem = mif_global->get_mifram_ptr(mif_global, 0); - - SCSC_TAG_INFO(MIF, "Phy addr :%p\n", mem); - - mif_global->mif_dump_registers(mif_global); - - return count; -} -/* - * TODO: Add here any debug message should be exported -static int mifprocfs_mif_dbg_show(struct seq_file *m, void *v) -{ - (void)v; - - if (!mif_global) { - seq_puts(m, "endpoint not registered"); - return 0; - } - return 0; -} -*/ - -/* Total space in the memory region containing this ramman (assumes one region per ramman) */ -static ssize_t mifprocfs_ramman_total_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct miframman *ramman = (struct miframman *)file->private_data; - - pos += scnprintf(buf + pos, bufsz - pos, "%zd\n", (ptrdiff_t)(ramman->start_dram - ramman->start_region) + ramman->size_pool); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -/* Offset of the pool within the region (the space before is reserved by FW) */ -static ssize_t mifprocfs_ramman_offset_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct miframman *ramman = (struct miframman *)file->private_data; - - pos += scnprintf(buf + pos, bufsz - pos, "%zd\n", (ptrdiff_t)(ramman->start_dram - ramman->start_region)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -/* Start address of the pool within the region */ -static ssize_t mifprocfs_ramman_start_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct miframman *ramman = (struct miframman *)file->private_data; - - pos += scnprintf(buf + pos, bufsz - pos, "%p\n", ramman->start_dram); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -/* Size of the pool */ -static ssize_t mifprocfs_ramman_size_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct miframman *ramman = (struct miframman *)file->private_data; - - pos += scnprintf(buf + pos, bufsz - pos, "%zd\n", ramman->size_pool); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -/* Space remaining within the pool */ -static ssize_t mifprocfs_ramman_free_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct miframman *ramman = (struct miframman *)file->private_data; - - pos += scnprintf(buf + pos, bufsz - pos, "%u\n", ramman->free_mem); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -/* Bytes used within the pool */ -static ssize_t mifprocfs_ramman_used_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct miframman *ramman = (struct miframman *)file->private_data; - - pos += scnprintf(buf + pos, bufsz - pos, "%zd\n", ramman->size_pool - (size_t)ramman->free_mem); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -/* List allocations per ramman */ -static int mifprocfs_ramman_list_show(struct seq_file *m, void *v) -{ - struct miframman *ramman = (struct miframman *)m->private; - (void)v; - - miframman_log(ramman, m); - - return 0; -} - -static const char *procdir = "driver/mif_ctrl"; -static int refcount; - -#define MIF_DIRLEN 128 - -static struct proc_dir_entry *create_procfs_dir(void) -{ - char dir[MIF_DIRLEN]; - - if (refcount++ == 0) { - (void)snprintf(dir, sizeof(dir), "%s", procdir); - procfs_dir = proc_mkdir(dir, NULL); - } - return procfs_dir; -} - -static void destroy_procfs_dir(void) -{ - char dir[MIF_DIRLEN]; - - if (--refcount == 0) { - (void)snprintf(dir, sizeof(dir), "%s", procdir); - remove_proc_entry(dir, NULL); - procfs_dir = NULL; - } - WARN_ON(refcount < 0); -} - - -int mifproc_create_proc_dir(struct scsc_mif_abs *mif) -{ - struct proc_dir_entry *parent; - - /* WARNING --- SINGLETON FOR THE TIME BEING */ - /* EXTEND PROC ENTRIES IF NEEDED!!!!! */ - if (mif_global) - return -EBUSY; - - /* Ref the root dir */ - parent = create_procfs_dir(); - if (parent) { -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = NULL; -#endif - MIF_PROCFS_ADD_FILE(NULL, mif_writemem, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MIF_PROCFS_ADD_FILE(NULL, mif_dump, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MIF_PROCFS_ADD_FILE(NULL, mif_reg, parent, S_IRUSR | S_IRGRP); - } else { - SCSC_TAG_INFO(MIF, "failed to create /proc dir\n"); - return -EINVAL; - } - - mif_global = mif; - - return 0; -/* -err: - return -EINVAL; -*/ -} - -void mifproc_remove_proc_dir(void) -{ - if (procfs_dir) { - MIF_PROCFS_REMOVE_FILE(mif_writemem, procfs_dir); - MIF_PROCFS_REMOVE_FILE(mif_dump, procfs_dir); - MIF_PROCFS_REMOVE_FILE(mif_reg, procfs_dir); - - /* De-ref the root dir */ - destroy_procfs_dir(); - } - - mif_global = NULL; -} - -/* /proc/driver/mif_ctrl/rammanX */ -static const char *ramman_procdir = "ramman"; -struct miframman *proc_miframman[MX_MAX_PROC_RAMMAN]; -static int ramman_instance; - -int mifproc_create_ramman_proc_dir(struct miframman *ramman) -{ - char dir[MIF_DIRLEN]; - struct proc_dir_entry *parent; - struct proc_dir_entry *root; - - if ((ramman_instance > ARRAY_SIZE(proc_miframman) - 1)) - return -EINVAL; - - /* Ref the root dir /proc/driver/mif_ctrl */ - root = create_procfs_dir(); - if (!root) - return -EINVAL; - - (void)snprintf(dir, sizeof(dir), "%s%d", ramman_procdir, ramman_instance); - parent = proc_mkdir(dir, root); - if (parent) { -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = NULL; -#endif - MIF_PROCFS_ADD_FILE(ramman, ramman_total, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MIF_PROCFS_ADD_FILE(ramman, ramman_offset, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MIF_PROCFS_ADD_FILE(ramman, ramman_start, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MIF_PROCFS_ADD_FILE(ramman, ramman_size, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MIF_PROCFS_ADD_FILE(ramman, ramman_free, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - MIF_PROCFS_ADD_FILE(ramman, ramman_used, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - - MIF_PROCFS_SEQ_ADD_FILE(ramman, ramman_list, parent, S_IRUSR | S_IRGRP | S_IROTH); - - procfs_dir_ramman[ramman_instance] = parent; - proc_miframman[ramman_instance] = ramman; - - ramman_instance++; - - } else { - SCSC_TAG_INFO(MIF, "failed to create /proc dir\n"); - destroy_procfs_dir(); - return -EINVAL; - } - - return 0; -} - -void mifproc_remove_ramman_proc_dir(struct miframman *ramman) -{ - (void)ramman; - - if (ramman_instance <= 0) { - WARN_ON(ramman_instance < 0); - return; - } - - --ramman_instance; - - if (procfs_dir_ramman[ramman_instance]) { - char dir[MIF_DIRLEN]; - - MIF_PROCFS_REMOVE_FILE(ramman_total, procfs_dir_ramman[ramman_instance]); - MIF_PROCFS_REMOVE_FILE(ramman_offset, procfs_dir_ramman[ramman_instance]); - MIF_PROCFS_REMOVE_FILE(ramman_start, procfs_dir_ramman[ramman_instance]); - MIF_PROCFS_REMOVE_FILE(ramman_size, procfs_dir_ramman[ramman_instance]); - MIF_PROCFS_REMOVE_FILE(ramman_free, procfs_dir_ramman[ramman_instance]); - MIF_PROCFS_REMOVE_FILE(ramman_used, procfs_dir_ramman[ramman_instance]); - - MIF_PROCFS_REMOVE_FILE(ramman_list, procfs_dir_ramman[ramman_instance]); - - (void)snprintf(dir, sizeof(dir), "%s%d", ramman_procdir, ramman_instance); - remove_proc_entry(dir, procfs_dir); - procfs_dir_ramman[ramman_instance] = NULL; - proc_miframman[ramman_instance] = NULL; - } - - /* De-ref the root dir */ - destroy_procfs_dir(); -} diff --git a/drivers/misc/samsung/scsc/mifproc.h b/drivers/misc/samsung/scsc/mifproc.h deleted file mode 100644 index ea92c5bf264d..000000000000 --- a/drivers/misc/samsung/scsc/mifproc.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* - * Chip Manager /proc interface - */ -#include -#include -#include - -#ifndef SCSC_MIF_PROC_H -#define SCSC_MIF_PROC_H - -#ifndef AID_MX -#define AID_MX 0444 -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MIF_PDE_DATA(inode) PDE_DATA(inode) -#else -#define MIF_PDE_DATA(inode) (PDE(inode)->data) -#endif - -#define MIF_PROCFS_SEQ_FILE_OPS(name) \ - static int mifprocfs_ ## name ## _show(struct seq_file *m, void *v); \ - static int mifprocfs_ ## name ## _open(struct inode *inode, struct file *file) \ - { \ - return single_open(file, mifprocfs_ ## name ## _show, MIF_PDE_DATA(inode)); \ - } \ - static const struct file_operations mifprocfs_ ## name ## _fops = { \ - .open = mifprocfs_ ## name ## _open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - } - -#define MIF_PROCFS_SEQ_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = proc_create_data(# name, mode, parent, &mifprocfs_ ## name ## _fops, _sdev); \ - if (!entry) { \ - break; \ - } \ - MIF_PROCFS_SET_UID_GID(entry); \ - } while (0) - -#define MIF_PROCFS_RW_FILE_OPS(name) \ - static ssize_t mifprocfs_ ## name ## _write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); \ - static ssize_t mifprocfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations mifprocfs_ ## name ## _fops = { \ - .read = mifprocfs_ ## name ## _read, \ - .write = mifprocfs_ ## name ## _write, \ - .open = mifprocfs_open_file_generic, \ - .llseek = generic_file_llseek \ - } - - -#define MIF_PROCFS_RO_FILE_OPS(name) \ - static ssize_t mifprocfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations mifprocfs_ ## name ## _fops = { \ - .read = mifprocfs_ ## name ## _read, \ - .open = mifprocfs_open_file_generic, \ - .llseek = generic_file_llseek \ - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MIF_PROCFS_SET_UID_GID(_entry) \ - do { \ - kuid_t proc_kuid = KUIDT_INIT(AID_MX); \ - kgid_t proc_kgid = KGIDT_INIT(AID_MX); \ - proc_set_user(_entry, proc_kuid, proc_kgid); \ - } while (0) -#else -#define MIF_PROCFS_SET_UID_GID(entry) \ - do { \ - (entry)->uid = AID_MX; \ - (entry)->gid = AID_MX; \ - } while (0) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MIF_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry = proc_create_data(# name, mode, parent, &mifprocfs_ ## name ## _fops, _sdev); \ - MIF_PROCFS_SET_UID_GID(entry); \ - } while (0) -#else -#define MIF_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = create_proc_entry(# name, mode, parent); \ - if (entry) { \ - entry->proc_fops = &mifprocfs_ ## name ## _fops; \ - entry->data = _sdev; \ - MIF_PROCFS_SET_UID_GID(entry); \ - } \ - } while (0) -#endif - -#define MIF_PROCFS_REMOVE_FILE(name, parent) remove_proc_entry(# name, parent) - -struct scsc_mif_abs; -struct miframman; - -int mifproc_create_proc_dir(struct scsc_mif_abs *mif); -void mifproc_remove_proc_dir(void); -int mifproc_create_ramman_proc_dir(struct miframman *miframman); -void mifproc_remove_ramman_proc_dir(struct miframman *miframman); - -struct mifproc { -}; -#endif /* SCSC_mif_PROC_H */ diff --git a/drivers/misc/samsung/scsc/mifqos.c b/drivers/misc/samsung/scsc/mifqos.c deleted file mode 100644 index 51d111a773ae..000000000000 --- a/drivers/misc/samsung/scsc/mifqos.c +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* uses */ -#include -#include -#include -#include -#include -#include "scsc_mif_abs.h" - -/* Implements */ -#include "mifqos.h" - -int mifqos_init(struct mifqos *qos, struct scsc_mif_abs *mif) -{ - u8 i; - - if (!qos) - return -EIO; - - SCSC_TAG_INFO(MIF, "Init MIF QoS\n"); - - for (i = 0; i < SCSC_SERVICE_TOTAL; i++) - qos->qos_in_use[i] = false; - - mutex_init(&qos->lock); - qos->mif = mif; - - return 0; -} - -int mifqos_add_request(struct mifqos *qos, enum scsc_service_id id, enum scsc_qos_config config) -{ - struct scsc_mif_abs *mif; - struct scsc_mifqos_request *req; - int ret = 0; - - if (!qos) - return -EIO; - - mutex_lock(&qos->lock); - if (qos->qos_in_use[id]) { - mutex_unlock(&qos->lock); - return -EIO; - } - - SCSC_TAG_INFO(MIF, "Service id %d add QoS request %d\n", id, config); - - mif = qos->mif; - req = &qos->qos_req[id]; - - if (mif->mif_pm_qos_add_request) - ret = mif->mif_pm_qos_add_request(mif, req, config); - if (ret) { - mutex_unlock(&qos->lock); - return ret; - } - qos->qos_in_use[id] = true; - mutex_unlock(&qos->lock); - - return 0; -} - -int mifqos_update_request(struct mifqos *qos, enum scsc_service_id id, enum scsc_qos_config config) -{ - struct scsc_mif_abs *mif; - struct scsc_mifqos_request *req; - - if (!qos) - return -EIO; - - mutex_lock(&qos->lock); - if (!qos->qos_in_use[id]) { - mutex_unlock(&qos->lock); - return -EIO; - } - - SCSC_TAG_INFO(MIF, "Service id %d update QoS request %d\n", id, config); - - mif = qos->mif; - req = &qos->qos_req[id]; - - mutex_unlock(&qos->lock); - - if (mif->mif_pm_qos_update_request) - return mif->mif_pm_qos_update_request(mif, req, config); - else - return 0; -} - -int mifqos_remove_request(struct mifqos *qos, enum scsc_service_id id) -{ - struct scsc_mif_abs *mif; - struct scsc_mifqos_request *req; - - if (!qos) - return -EIO; - - mutex_lock(&qos->lock); - if (!qos->qos_in_use[id]) { - mutex_unlock(&qos->lock); - return -EIO; - } - - SCSC_TAG_INFO(MIF, "Service id %d remove QoS\n", id); - - mif = qos->mif; - req = &qos->qos_req[id]; - - qos->qos_in_use[id] = false; - - mutex_unlock(&qos->lock); - - if (mif->mif_pm_qos_remove_request) - return mif->mif_pm_qos_remove_request(mif, req); - else - return 0; -} - -int mifqos_deinit(struct mifqos *qos) -{ - enum scsc_service_id i; - - SCSC_TAG_INFO(MIF, "Deinit MIF QoS\n"); - - for (i = 0; i < SCSC_SERVICE_TOTAL; i++) - mifqos_remove_request(qos, i); - - return 0; -} - diff --git a/drivers/misc/samsung/scsc/mifqos.h b/drivers/misc/samsung/scsc/mifqos.h deleted file mode 100644 index a9e7af9e596f..000000000000 --- a/drivers/misc/samsung/scsc/mifqos.h +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#ifndef __MIFQOS_H -#define __MIFQOS_H - -#include -#include - -struct scsc_mif_abs; -struct mifqos; - -int mifqos_init(struct mifqos *qos, struct scsc_mif_abs *mif); -int mifqos_add_request(struct mifqos *qos, enum scsc_service_id id, enum scsc_qos_config config); -int mifqos_update_request(struct mifqos *qos, enum scsc_service_id id, enum scsc_qos_config config); -int mifqos_remove_request(struct mifqos *qos, enum scsc_service_id id); -int mifqos_list(struct mifqos *qos); -int mifqos_deinit(struct mifqos *qos); - -struct scsc_mifqos_request; - -struct mifqos { - bool qos_in_use[SCSC_SERVICE_TOTAL]; - struct mutex lock; - struct scsc_mif_abs *mif; - struct scsc_mifqos_request qos_req[SCSC_SERVICE_TOTAL]; -}; -#endif diff --git a/drivers/misc/samsung/scsc/miframman.c b/drivers/misc/samsung/scsc/miframman.c deleted file mode 100644 index d2f16b135014..000000000000 --- a/drivers/misc/samsung/scsc/miframman.c +++ /dev/null @@ -1,267 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include "scsc_mif_abs.h" - -#include "scsc/api/bt_audio.h" -#include "miframman.h" -#include "mifproc.h" - -/* Caller should provide locking */ -void miframman_init(struct miframman *ram, void *start_dram, size_t size_pool, void *start_region) -{ - mutex_init(&ram->lock); - - SCSC_TAG_INFO(MIF, "MIFRAMMAN_BLOCK_SIZE = %d\n", MIFRAMMAN_BLOCK_SIZE); - ram->num_blocks = size_pool / MIFRAMMAN_BLOCK_SIZE; - - if (ram->num_blocks == 0) { - SCSC_TAG_ERR(MIF, "Pool size < BLOCK_SIZE\n"); - return; - } - - if (ram->num_blocks >= MIFRAMMAN_NUM_BLOCKS) { - SCSC_TAG_ERR(MIF, "Not enough memory\n"); - return; - } - - memset(ram->bitmap, BLOCK_FREE, sizeof(ram->bitmap)); - - ram->start_region = start_region; /* For monitoring purposes only */ - ram->start_dram = start_dram; - ram->size_pool = size_pool; - ram->free_mem = ram->num_blocks * MIFRAMMAN_BLOCK_SIZE; - - mifproc_create_ramman_proc_dir(ram); -} - -void miframabox_init(struct mifabox *mifabox, void *start_aboxram) -{ - /* No locking as not a shared resource */ - mifabox->aboxram = (struct scsc_bt_audio_abox *)start_aboxram; -} - -void *__miframman_alloc(struct miframman *ram, size_t nbytes, int tag) -{ - unsigned int index = 0; - unsigned int available; - unsigned int i; - size_t num_blocks; - void *free_mem = NULL; - - if (!nbytes || nbytes > ram->free_mem) - goto end; - - /* Number of blocks required (rounding up) */ - num_blocks = nbytes / MIFRAMMAN_BLOCK_SIZE + - ((nbytes % MIFRAMMAN_BLOCK_SIZE) > 0 ? 1 : 0); - - if (num_blocks > ram->num_blocks) - goto end; - - while (index <= (ram->num_blocks - num_blocks)) { - available = 0; - - /* Search consecutive blocks */ - for (i = 0; i < num_blocks; i++) { - if (ram->bitmap[i + index] != BLOCK_FREE) - break; - available++; - } - if (available == num_blocks) { - free_mem = ram->start_dram + - MIFRAMMAN_BLOCK_SIZE * index; - - /* Mark the block boundary as used */ - ram->bitmap[index] = BLOCK_BOUND; - ram->bitmap[index] |= (u8)(tag << MIFRAMMAN_BLOCK_OWNER_SHIFT); /* Add owner tack for tracking */ - index++; - - /* Additional blocks in this allocation */ - for (i = 1; i < num_blocks; i++) { - ram->bitmap[index] = BLOCK_INUSE; - ram->bitmap[index] |= (u8)(tag << MIFRAMMAN_BLOCK_OWNER_SHIFT); /* Add owner tack for tracking */ - index++; - } - - ram->free_mem -= num_blocks * MIFRAMMAN_BLOCK_SIZE; - goto exit; - } else - index = index + available + 1; - } -end: - SCSC_TAG_INFO(MIF, "Not enough shared memory (nbytes %zd, free_mem %u)\n", - nbytes, ram->free_mem); - return NULL; -exit: - return free_mem; -} - - -#define MIFRAMMAN_ALIGN(mem, align) \ - ((void *)((((uintptr_t)(mem) + (align + sizeof(void *))) \ - & (~(uintptr_t)(align - 1))))) - -#define MIFRAMMAN_PTR(mem) \ - (*(((void **)((uintptr_t)(mem) & \ - (~(uintptr_t)(sizeof(void *) - 1)))) - 1)) - -/* - * Allocate shared DRAM block - * - * Parameters: - * ram - pool identifier - * nbytes - allocation size - * align - allocation alignment - * tag - owner identifier (typically service ID), 4 bits. - * - * Returns - * Pointer to allocated area, or NULL - */ -void *miframman_alloc(struct miframman *ram, size_t nbytes, size_t align, int tag) -{ - void *mem, *align_mem = NULL; - - mutex_lock(&ram->lock); - if (!is_power_of_2(align) || nbytes == 0) { - SCSC_TAG_ERR(MIF, "Failed size/alignment check (nbytes %zd, align %zd)\n", nbytes, align); - goto end; - } - - if (align < sizeof(void *)) - align = sizeof(void *); - - mem = __miframman_alloc(ram, nbytes + align + sizeof(void *), tag); - if (!mem) - goto end; - - align_mem = MIFRAMMAN_ALIGN(mem, align); - - /* Store allocated pointer */ - MIFRAMMAN_PTR(align_mem) = mem; -end: - mutex_unlock(&ram->lock); - return align_mem; -} - -/* - * Free shared DRAM block - * - * Parameters: - * ram - pool identifier - * mem - buffer to free - */ -void __miframman_free(struct miframman *ram, void *mem) -{ - unsigned int index, num_blocks = 0; - - if (ram->start_dram == NULL || !mem) { - SCSC_TAG_ERR(MIF, "Mem is NULL\n"); - return; - } - - /* Get block index */ - index = (unsigned int)((mem - ram->start_dram) - / MIFRAMMAN_BLOCK_SIZE); - - /* Check */ - if (index >= ram->num_blocks) { - SCSC_TAG_ERR(MIF, "Incorrect index %d\n", index); - return; - } - - /* Check it is a Boundary block */ - if ((ram->bitmap[index] & MIFRAMMAN_BLOCK_STATUS_MASK) != BLOCK_BOUND) { - SCSC_TAG_ERR(MIF, "Incorrect Block descriptor\n"); - return; - } - ram->bitmap[index++] = BLOCK_FREE; - - /* Free remaining blocks */ - num_blocks++; - while (index < ram->num_blocks && (ram->bitmap[index] & MIFRAMMAN_BLOCK_STATUS_MASK) == BLOCK_INUSE) { - ram->bitmap[index++] = BLOCK_FREE; - num_blocks++; - } - - ram->free_mem += num_blocks * MIFRAMMAN_BLOCK_SIZE; -} - -void miframman_free(struct miframman *ram, void *mem) -{ - mutex_lock(&ram->lock); - /* Restore allocated pointer */ - if (mem) - __miframman_free(ram, MIFRAMMAN_PTR(mem)); - mutex_unlock(&ram->lock); -} - -/* Caller should provide locking */ -void miframman_deinit(struct miframman *ram) -{ - /* Mark all the blocks as INUSE (by Common) to prevent new allocations */ - memset(ram->bitmap, BLOCK_INUSE, sizeof(ram->bitmap)); - - ram->num_blocks = 0; - ram->start_dram = NULL; - ram->size_pool = 0; - ram->free_mem = 0; - - mifproc_remove_ramman_proc_dir(ram); -} - -void miframabox_deinit(struct mifabox *mifabox) -{ - /* not dynamic - so just mark as NULL */ - /* Maybe this function should be empty? */ - mifabox->aboxram = NULL; -} - -/* Log current allocations in a ramman in proc */ -void miframman_log(struct miframman *ram, struct seq_file *fd) -{ - unsigned int b; - unsigned int i; - int tag; - size_t num_blocks = 0; - - if (!ram) - return; - - seq_printf(fd, "ramman: start_dram %p, size %zd, free_mem %u\n\n", - ram->start_region, ram->size_pool, ram->free_mem); - - for (b = 0; b < ram->num_blocks; b++) { - if ((ram->bitmap[b] & MIFRAMMAN_BLOCK_STATUS_MASK) == BLOCK_BOUND) { - /* Found a boundary allocation */ - num_blocks++; - tag = (ram->bitmap[b] & MIFRAMMAN_BLOCK_OWNER_MASK) >> MIFRAMMAN_BLOCK_OWNER_SHIFT; - - /* Count subsequent blocks in this group */ - for (i = 1; - i < ram->num_blocks && (ram->bitmap[b + i] & MIFRAMMAN_BLOCK_STATUS_MASK) == BLOCK_INUSE; - i++) { - /* Check owner matches boundary block */ - int newtag = (ram->bitmap[b + i] & MIFRAMMAN_BLOCK_OWNER_MASK) >> MIFRAMMAN_BLOCK_OWNER_SHIFT; - if (newtag != tag) { - seq_printf(fd, "Allocated block tag %d doesn't match boundary tag %d, index %d, %p\n", - newtag, tag, b + i, - ram->start_dram + (b + i) * MIFRAMMAN_BLOCK_SIZE); - } - num_blocks++; - } - seq_printf(fd, "index %8d, svc %d, bytes %12d, blocks %10d, %p\n", - b, tag, - (i * MIFRAMMAN_BLOCK_SIZE), - i, - ram->start_dram + (b * MIFRAMMAN_BLOCK_SIZE)); - } - } -} diff --git a/drivers/misc/samsung/scsc/miframman.h b/drivers/misc/samsung/scsc/miframman.h deleted file mode 100644 index acce9dac4daf..000000000000 --- a/drivers/misc/samsung/scsc/miframman.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MIFRAMMAN_H -#define __MIFRAMMAN_H - -#include -#include "scsc/api/bt_audio.h" - -/* TODO: Needs to define the max mem */ - -struct miframman; -struct mifabox; - - -void miframman_init(struct miframman *ram, void *start_dram, size_t size_pool, void *start_region); -void miframabox_init(struct mifabox *mifabox, void *start_aboxram); -void *miframman_alloc(struct miframman *ram, size_t nbytes, size_t align, int tag); -void miframman_free(struct miframman *ram, void *mem); -void miframman_deinit(struct miframman *ram); -void miframabox_deinit(struct mifabox *mifabox); -void miframman_log(struct miframman *ram, struct seq_file *fd); - -#define MIFRAMMAN_MAXMEM (16 * 1024 * 1024) -#define MIFRAMMAN_BLOCK_SIZE (64) - -#define MIFRAMMAN_NUM_BLOCKS ((MIFRAMMAN_MAXMEM) / (MIFRAMMAN_BLOCK_SIZE)) - -/* Block status in lower nibble */ -#define MIFRAMMAN_BLOCK_STATUS_MASK 0x0f -#define BLOCK_FREE 0 -#define BLOCK_INUSE 1 -#define BLOCK_BOUND 2 /* Block allocation boundary */ - -/* Block owner in upper nibble */ -#define MIFRAMMAN_BLOCK_OWNER_MASK 0xf0 -#define MIFRAMMAN_BLOCK_OWNER_SHIFT 4 - -#define MIFRAMMAN_OWNER_COMMON 0 /* Owner tag for Common driver */ - -/* Inclusion in core.c treat it as opaque */ -struct miframman { - void *start_region; /* Base address of region containing the pool */ - void *start_dram; /* Base address of allocator pool */ - size_t size_pool; /* Size of allocator pool */ - char bitmap[MIFRAMMAN_NUM_BLOCKS]; /* Zero initialized-> all blocks free */ - u32 num_blocks; /* Blocks of MIFRAMMAN_BLOCK_SIZE in pool */ - u32 free_mem; /* Bytes remaining in allocator pool */ - struct mutex lock; -}; - -struct mifabox { - struct scsc_bt_audio_abox *aboxram; -}; -#endif diff --git a/drivers/misc/samsung/scsc/mifsmapper.c b/drivers/misc/samsung/scsc/mifsmapper.c deleted file mode 100644 index aedaeca7970d..000000000000 --- a/drivers/misc/samsung/scsc/mifsmapper.c +++ /dev/null @@ -1,360 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* uses */ -#include -#include -#include -#include -#include -#include "scsc_mif_abs.h" - -/* Implements */ -#include "mifsmapper.h" - - -static int mifsmapper_get_num_banks(u8 *phy_map, u8 *log_map, bool large) -{ - u8 i = 0, count = 0; - - for (i = 0; i < SCSC_MIF_SMAPPER_MAX_BANKS; i++) { - if (large && phy_map[i] == SCSC_MIF_ABS_LARGE_BANK) { - log_map[count] = i; - count++; - } else if (!large && phy_map[i] == SCSC_MIF_ABS_SMALL_BANK) { - log_map[count] = i; - count++; - } - } - - return count; -} - -int mifsmapper_init(struct mifsmapper *smapper, struct scsc_mif_abs *mif) -{ - /* TODO: Protect the function if allocations fail */ - struct scsc_mif_smapper_info bank_info; - u8 i = 0, total_num_banks; - u8 phy_map[SCSC_MIF_SMAPPER_MAX_BANKS] = { 0 }; - u8 log_map_large[SCSC_MIF_SMAPPER_MAX_BANKS] = { 0 }; - u8 log_map_small[SCSC_MIF_SMAPPER_MAX_BANKS] = { 0 }; - - if (smapper->in_use) - return -EBUSY; - - SCSC_TAG_INFO(MIF, "Init SMAPPER\n"); - - spin_lock_init(&smapper->lock); - /* Get physical mapping of the banks */ - if (mif->mif_smapper_get_mapping(mif, phy_map, &smapper->align)) { - SCSC_TAG_ERR(MIF, "SMAPPER is not present\n"); - return -EINVAL; - } - - smapper->in_use = true; - smapper->mif = mif; - - smapper->num_large_banks = mifsmapper_get_num_banks(phy_map, log_map_large, true); - smapper->num_small_banks = mifsmapper_get_num_banks(phy_map, log_map_small, false); - total_num_banks = smapper->num_large_banks + smapper->num_small_banks; - - smapper->bank = kmalloc_array(total_num_banks, sizeof(struct mifsmapper_bank), - GFP_KERNEL); - - smapper->bank_bm_large = kmalloc(BITS_TO_LONGS(smapper->num_large_banks) * sizeof(unsigned long), GFP_KERNEL); - bitmap_zero(smapper->bank_bm_large, smapper->num_large_banks); - - smapper->bank_bm_small = kmalloc(BITS_TO_LONGS(smapper->num_small_banks) * sizeof(unsigned long), GFP_KERNEL); - bitmap_zero(smapper->bank_bm_small, smapper->num_small_banks); - - /* LSB bit of banks will be the large banks the rest will be the small banks */ - /* Get large bank info */ - for (; i < smapper->num_large_banks; i++) { - /* get phy bank */ - mif->mif_smapper_get_bank_info(mif, log_map_large[i], &bank_info); - smapper->bank[i].entries_bm = kmalloc(BITS_TO_LONGS(bank_info.num_entries) * sizeof(unsigned long), GFP_KERNEL); - smapper->bank[i].num_entries = bank_info.num_entries; - smapper->bank[i].mem_range_bytes = bank_info.mem_range_bytes; - smapper->bank[i].phy_index = log_map_large[i]; - SCSC_TAG_INFO(MIF, "phy bank %d mapped to logical %d. Large, entries %d range 0x%x\n", - log_map_large[i], i, bank_info.num_entries, bank_info.mem_range_bytes); - bitmap_zero(smapper->bank[i].entries_bm, bank_info.num_entries); - } - - /* Get small bank info */ - for (; i < total_num_banks; i++) { - /* get phy bank */ - mif->mif_smapper_get_bank_info(mif, log_map_small[i - smapper->num_large_banks], &bank_info); - smapper->bank[i].entries_bm = kmalloc(BITS_TO_LONGS(bank_info.num_entries) * sizeof(unsigned long), GFP_KERNEL); - smapper->bank[i].num_entries = bank_info.num_entries; - smapper->bank[i].mem_range_bytes = bank_info.mem_range_bytes; - smapper->bank[i].phy_index = log_map_small[i - smapper->num_large_banks]; - SCSC_TAG_INFO(MIF, "phy bank %d mapped to logical %d. Small, entries %d range 0x%x\n", - log_map_small[i - smapper->num_large_banks], i, bank_info.num_entries, bank_info.mem_range_bytes); - bitmap_zero(smapper->bank[i].entries_bm, bank_info.num_entries); - } - - return 0; -} - -u16 mifsmapper_get_alignment(struct mifsmapper *smapper) -{ - return smapper->align; -} - -int mifsmapper_alloc_bank(struct mifsmapper *smapper, bool large_bank, u32 entry_size, u16 *entries) -{ - struct mifsmapper_bank *bank; - unsigned long *bitmap; - u8 max_banks, offset = 0; - int which_bit = 0; - - spin_lock(&smapper->lock); - - if (!smapper->in_use) - goto error; - - bank = smapper->bank; - if (large_bank) { - max_banks = smapper->num_large_banks; - bitmap = smapper->bank_bm_large; - } else { - max_banks = smapper->num_small_banks; - bitmap = smapper->bank_bm_small; - offset = smapper->num_large_banks; - } - - /* Search for free slots */ - which_bit = find_first_zero_bit(bitmap, max_banks); - if (which_bit >= max_banks) - goto error; - - /* Update bit mask */ - set_bit(which_bit, bitmap); - - /* Retrieve Bank capabilities and return the number of entries available */ - /* size must be a power of 2 */ - /* TODO : check that granularity is correct */ - BUG_ON(!is_power_of_2(entry_size)); - - /* Clear bank entries */ - bitmap_zero(bank[which_bit + offset].entries_bm, bank[which_bit + offset].num_entries); - - *entries = bank[which_bit + offset].mem_range_bytes/entry_size; - /* Saturate */ - if (*entries > bank[which_bit + offset].num_entries) - *entries = bank[which_bit + offset].num_entries; - else if (*entries < bank[which_bit + offset].num_entries) { - u16 i; - - SCSC_TAG_INFO(MIF, "Nominal entries %d reduced to %d\n", - bank[which_bit + offset].num_entries, *entries); - - for (i = *entries; i < bank[which_bit + offset].num_entries; i++) - /* Mark the MSB of the bitmap as used */ - set_bit(i, bank[which_bit + offset].entries_bm); - } - /* Update number of entries */ - bank[which_bit + offset].num_entries = *entries; - bank[which_bit + offset].num_entries_left = *entries; - bank[which_bit + offset].in_use = true; - bank[which_bit + offset].granularity = entry_size; - - SCSC_TAG_INFO(MIF, "entries %d bank.num_entries %d large bank %d logical bank %d entries left %d\n", *entries, bank[which_bit + offset].num_entries, large_bank, which_bit + offset, - bank[which_bit + offset].num_entries_left); - - spin_unlock(&smapper->lock); - return which_bit + offset; - -error: - SCSC_TAG_ERR(MIF, "Error allocating bank\n"); - - *entries = 0; - spin_unlock(&smapper->lock); - return -EIO; -} - -int mifsmapper_free_bank(struct mifsmapper *smapper, u8 bank) -{ - unsigned long *bitmap; - u8 max_banks, offset = 0; - struct mifsmapper_bank *bank_en; - - spin_lock(&smapper->lock); - - if (!smapper->in_use || ((bank >= (smapper->num_large_banks + smapper->num_small_banks)))) - goto error; - - /* check if it is a large or small bank */ - if (bank >= smapper->num_large_banks) { - max_banks = smapper->num_small_banks; - bitmap = smapper->bank_bm_small; - offset = bank - smapper->num_large_banks; - } else { - max_banks = smapper->num_large_banks; - bitmap = smapper->bank_bm_large; - offset = bank; - } - - /* Update bit mask */ - if (!test_and_clear_bit(offset, bitmap)) - SCSC_TAG_ERR(MIF, "bank was not allocated\n"); - - bank_en = smapper->bank; - bank_en[bank].in_use = false; - - spin_unlock(&smapper->lock); - - return 0; -error: - SCSC_TAG_ERR(MIF, "Error freeing bank %d\n", bank); - spin_unlock(&smapper->lock); - - return -EIO; -} - -int mifsmapper_get_entries(struct mifsmapper *smapper, u8 bank, u8 num_entries, u8 *entries) -{ - struct mifsmapper_bank *bank_en; - unsigned long *bitmap; - u32 max_bits, i, ent; - - if (!smapper->bank) - return -EINVAL; - - bank_en = smapper->bank; - - if (!bank_en[bank].in_use) { - SCSC_TAG_ERR(MIF, "Bank %d not allocated.\n", bank); - return -EINVAL; - } - - - max_bits = bank_en[bank].num_entries_left; - ent = bank_en[bank].num_entries; - if (num_entries > max_bits) { - SCSC_TAG_ERR(MIF, "Not enough entries. Requested %d, left %d\n", num_entries, max_bits); - return -ENOMEM; - } - - bitmap = bank_en[bank].entries_bm; - - for (i = 0; i < num_entries; i++) { - entries[i] = find_first_zero_bit(bitmap, ent); - if (entries[i] >= ent) - return -EIO; - /* Update bit mask */ - set_bit(entries[i], bitmap); - } - - smapper->bank[bank].num_entries_left -= num_entries; - - return 0; -} - -int mifsmapper_free_entries(struct mifsmapper *smapper, u8 bank, u8 num_entries, u8 *entries) -{ - struct mifsmapper_bank *bank_en; - unsigned long *bitmap; - u32 max_bits, i, ent, total = 0; - - if (!smapper->bank) - return -EINVAL; - - bank_en = smapper->bank; - - if (!bank_en[bank].in_use) { - SCSC_TAG_ERR(MIF, "Bank %d not allocated.\n", bank); - return -EINVAL; - } - - - max_bits = bank_en[bank].num_entries_left; - ent = bank_en[bank].num_entries; - if ((max_bits + num_entries) > ent) { - SCSC_TAG_ERR(MIF, "Tried to free more entries. Requested %d, left %d\n", num_entries, max_bits); - return -ENOMEM; - } - - bitmap = bank_en[bank].entries_bm; - - for (i = 0; i < num_entries; i++) { - /* Update bit mask */ - if (!test_and_clear_bit(entries[i], bitmap)) - SCSC_TAG_ERR(MIF, "entry was not allocated\n"); - else - total++; - } - - smapper->bank[bank].num_entries_left += total; - - return 0; -} - -void mifsmapper_configure(struct mifsmapper *smapper, u32 granularity) -{ - struct scsc_mif_abs *mif; - /* Get abs implementation */ - mif = smapper->mif; - - mif->mif_smapper_configure(mif, granularity); -} - -int mifsmapper_write_sram(struct mifsmapper *smapper, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr) -{ - struct scsc_mif_abs *mif; - - if (!smapper->bank[bank].in_use) { - SCSC_TAG_ERR(MIF, "Bank %d not allocated.\n", bank); - return -EINVAL; - } - - /* Get abs implementation */ - mif = smapper->mif; - - /* use the phy address of the bank */ - return mif->mif_smapper_write_sram(mif, smapper->bank[bank].phy_index, num_entries, first_entry, addr); -} - -u32 mifsmapper_get_bank_base_address(struct mifsmapper *smapper, u8 bank) -{ - struct scsc_mif_abs *mif; - - /* Get abs implementation */ - mif = smapper->mif; - - return mif->mif_smapper_get_bank_base_address(mif, bank); -} - -int mifsmapper_deinit(struct mifsmapper *smapper) -{ - u8 i = 0, total_num_banks; - - spin_lock(&smapper->lock); - - SCSC_TAG_INFO(MIF, "Deinit SMAPPER\n"); - - if (!smapper->in_use) { - spin_unlock(&smapper->lock); - return -ENODEV; - } - - total_num_banks = smapper->num_large_banks + smapper->num_small_banks; - for (; i < total_num_banks; i++) { - kfree(smapper->bank[i].entries_bm); - smapper->bank[i].num_entries = 0; - smapper->bank[i].mem_range_bytes = 0; - } - - kfree(smapper->bank_bm_large); - kfree(smapper->bank_bm_small); - kfree(smapper->bank); - - smapper->in_use = false; - - spin_unlock(&smapper->lock); - return 0; -} diff --git a/drivers/misc/samsung/scsc/mifsmapper.h b/drivers/misc/samsung/scsc/mifsmapper.h deleted file mode 100644 index 715f1f5503a8..000000000000 --- a/drivers/misc/samsung/scsc/mifsmapper.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#ifndef __MIFSMAPPER_H -#define __MIFSMAPPER_H - -#include - -struct mifsmapper; -struct scsc_mif_abs; -struct mutex; - -int mifsmapper_init(struct mifsmapper *smapper, struct scsc_mif_abs *mif); -u16 mifsmapper_get_alignment(struct mifsmapper *smapper); -int mifsmapper_alloc_bank(struct mifsmapper *smapper, bool large_bank, u32 entry_size, u16 *entries); -int mifsmapper_free_bank(struct mifsmapper *smapper, u8 bank); -int mifsmapper_get_entries(struct mifsmapper *smapper, u8 bank, u8 num_entries, u8 *entr); -int mifsmapper_free_entries(struct mifsmapper *smapper, u8 bank, u8 num_entries, u8 *entries); -void mifsmapper_configure(struct mifsmapper *smapper, u32 granularity); -int mifsmapper_write_sram(struct mifsmapper *smapper, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr); -u32 mifsmapper_get_bank_base_address(struct mifsmapper *smapper, u8 bank); -int mifsmapper_deinit(struct mifsmapper *smapper); - -#define MIFSMAPPER_160 4 -#define MIFSMAPPER_64 7 - -#define MIFSMAPPER_NOT_VALID 0 -#define MIFSMAPPER_VALID 1 - -struct mifsmapper_bank { - unsigned long *entries_bm; - u32 num_entries; - u32 num_entries_left; - u32 mem_range_bytes; - u8 phy_index; - u32 granularity; - bool in_use; -}; - -/* Inclusion in core.c treat it as opaque */ -struct mifsmapper { - bool in_use; - spinlock_t lock; - struct scsc_mif_abs *mif; - struct mifsmapper_bank *bank; /* Bank reference created after reading HW capabilities */ - unsigned long *bank_bm_large; - unsigned long *bank_bm_small; - u32 num_large_banks; - u32 num_small_banks; - u16 align; -}; -#endif diff --git a/drivers/misc/samsung/scsc/mifstream.c b/drivers/misc/samsung/scsc/mifstream.c deleted file mode 100644 index 6cbb664f565c..000000000000 --- a/drivers/misc/samsung/scsc/mifstream.c +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * MIF Byte Stream (Implementation) - */ - -/* Implements */ -#include "scsc_mx_impl.h" -#include "mifstream.h" - -/* Uses */ -#include "mifintrbit.h" - -/* Public Functions */ - -void mif_stream_config_serialise(struct mif_stream *stream, struct mxstreamconf *stream_conf) -{ - stream_conf->read_bit_idx = stream->read_bit_idx; - stream_conf->write_bit_idx = stream->write_bit_idx; - cpacketbuffer_config_serialise(&stream->buffer, &stream_conf->buf_conf); -} - -int mif_stream_init(struct mif_stream *stream, enum scsc_mif_abs_target target, enum MIF_STREAM_DIRECTION direction, uint32_t num_packets, uint32_t packet_size, - struct scsc_mx *mx, enum MIF_STREAM_INTRBIT_TYPE intrbit, mifintrbit_handler tohost_irq_handler, void *data) -{ - struct mifintrbit *intr; - int r, r1, r2; - - stream->mx = mx; - r = cpacketbuffer_init(&stream->buffer, num_packets, packet_size, mx); - if (r) - return r; - - intr = scsc_mx_get_intrbit(mx); - - r1 = mifintrbit_alloc_tohost(intr, tohost_irq_handler, data); - if (r1 < 0) { - cpacketbuffer_release(&stream->buffer); - return r1; - } - - /** - * MIF interrupt bit 0 in both the to-r4 and to-m4 registers are reserved - * for purpose of forcing panics from the MX Manager directly or via the - * gdb monitor stacks. - * - * At stream initialization the gdb transport requests for the reserved bits - * rather than dynamic allocation of interrupt bits. - * - * So if the interrupt bit type requested is Reserved, just Assign the pre- - * reserved interrupt bits. - */ - if (intrbit == MIF_STREAM_INTRBIT_TYPE_RESERVED) { - if (target == SCSC_MIF_ABS_TARGET_M4) - r2 = MIFINTRBIT_RESERVED_PANIC_M4; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - else if (target == SCSC_MIF_ABS_TARGET_M4_1) - r2 = MIFINTRBIT_RESERVED_PANIC_M4_1; -#endif - else - r2 = MIFINTRBIT_RESERVED_PANIC_R4; - } else - r2 = mifintrbit_alloc_fromhost(intr, target); - - if (r2 < 0) { - cpacketbuffer_release(&stream->buffer); - mifintrbit_free_tohost(intr, r1); - return r2; - } - switch (direction) { - case MIF_STREAM_DIRECTION_OUT: - stream->read_bit_idx = r1; - stream->write_bit_idx = r2; - break; - case MIF_STREAM_DIRECTION_IN: - /* Default value for the shared memory region */ - memset(stream->buffer.buffer, 0xff, num_packets * packet_size); - /* Commit */ - smp_wmb(); - stream->read_bit_idx = r2; - stream->write_bit_idx = r1; - break; - default: - cpacketbuffer_release(&stream->buffer); - mifintrbit_free_tohost(intr, r1); - mifintrbit_free_fromhost(intr, r2, target); - return -EINVAL; - } - stream->direction = direction; - stream->peer = (enum MIF_STREAM_PEER)target; - return 0; -} - -void mif_stream_release(struct mif_stream *stream) -{ - struct mifintrbit *intr; - - intr = scsc_mx_get_intrbit(stream->mx); - if (stream->direction == MIF_STREAM_DIRECTION_IN) { - mifintrbit_free_tohost(intr, stream->write_bit_idx); - mifintrbit_free_fromhost(intr, stream->read_bit_idx, (enum scsc_mif_abs_target)stream->peer); - } else { - mifintrbit_free_tohost(intr, stream->read_bit_idx); - mifintrbit_free_fromhost(intr, stream->write_bit_idx, (enum scsc_mif_abs_target)stream->peer); - } - cpacketbuffer_release(&stream->buffer); -} - -uint32_t mif_stream_read(struct mif_stream *stream, void *buf, uint32_t num_bytes) -{ - struct scsc_mif_abs *mif_abs = scsc_mx_get_mif_abs(stream->mx); - - uint32_t num_bytes_read = cpacketbuffer_read(&stream->buffer, buf, num_bytes); - - if (num_bytes_read > 0) - /* Signal that the read is finished to anyone interested */ - mif_abs->irq_bit_set(mif_abs, stream->read_bit_idx, (enum scsc_mif_abs_target)stream->peer); - - return num_bytes_read; -} - -const void *mif_stream_peek(struct mif_stream *stream, const void *current_packet) -{ - return cpacketbuffer_peek(&stream->buffer, current_packet); -} - -void mif_stream_peek_complete(struct mif_stream *stream, const void *packet) -{ - struct scsc_mif_abs *mif_abs = scsc_mx_get_mif_abs(stream->mx); - - cpacketbuffer_peek_complete(&stream->buffer, packet); - - /* Signal that the read is finished to anyone interested */ - mif_abs->irq_bit_set(mif_abs, stream->read_bit_idx, (enum scsc_mif_abs_target)stream->peer); -} - -bool mif_stream_write(struct mif_stream *stream, const void *buf, uint32_t num_bytes) -{ - struct scsc_mif_abs *mif_abs = scsc_mx_get_mif_abs(stream->mx); - - if (!cpacketbuffer_write(&stream->buffer, buf, num_bytes)) - return false; - - /* Kick the assigned interrupt to let others know new data is available */ - mif_abs->irq_bit_set(mif_abs, stream->write_bit_idx, (enum scsc_mif_abs_target)stream->peer); - - return true; -} - -bool mif_stream_write_gather(struct mif_stream *stream, const void **bufs, uint32_t *lengths, uint32_t num_bufs) -{ - struct scsc_mif_abs *mif_abs = scsc_mx_get_mif_abs(stream->mx); - - if (!cpacketbuffer_write_gather(&stream->buffer, bufs, lengths, num_bufs)) - return false; - - /* Kick the assigned interrupt to let others know new data is available */ - mif_abs->irq_bit_set(mif_abs, stream->write_bit_idx, (enum scsc_mif_abs_target)stream->peer); - return true; -} - -uint32_t mif_stream_block_size(struct mif_stream *stream) -{ - return cpacketbuffer_packet_size(&stream->buffer); -} - -uint8_t mif_stream_read_interrupt(struct mif_stream *stream) -{ - return stream->read_bit_idx; -} - -uint8_t mif_stream_write_interrupt(struct mif_stream *stream) -{ - return stream->write_bit_idx; -} - -void mif_stream_log(const struct mif_stream *stream, enum scsc_log_level log_level) -{ - cpacketbuffer_log(&stream->buffer, log_level); -} - diff --git a/drivers/misc/samsung/scsc/mifstream.h b/drivers/misc/samsung/scsc/mifstream.h deleted file mode 100644 index fe02a0bde2a3..000000000000 --- a/drivers/misc/samsung/scsc/mifstream.h +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * MIF stream (Interface) - * - * Provides a one-way communication mechanism between two points. The consumer side - * will be notified via an interrupt when the producer side writes data to the - * stream, and likewise the producer will be notified when the consumer has read - * data from the stream. - * - * It is expected that the data sent across the stream consists of fixed-size - * packets, and that the underlying storage mechanism is initialised to use a packet size - * that is at least as large as the largest message size. If this is not the case, - * callers are responsible for handling reading of partial messages from the stream - * in multiples of the packet size. - */ - -#ifndef MIFSTREAM_H__ -#define MIFSTREAM_H__ - -/* Uses */ - -#include "cpacket_buffer.h" -#include "mifintrbit.h" -#include "scsc_logring_common.h" - -/* Public Types */ - -enum MIF_STREAM_PEER { - MIF_STREAM_PEER_R4, - MIF_STREAM_PEER_M4, -}; - -enum MIF_STREAM_DIRECTION { - MIF_STREAM_DIRECTION_IN, - MIF_STREAM_DIRECTION_OUT, -}; - -/** - * Defines for the MIF Stream interrupt bits - * - * MIF_STREAM_INTRBIT_TYPE_RESERVED: the bits are reserved - * at initialization and are assigned to GDB transport channels. - * It is for purpose of forcing Panics from either MX manager or GDB - * - * MIF_STREAM_INTRBIT_TYPE_ALLOC: the bits are allocated dynamically - * when a stream is initialized - */ -enum MIF_STREAM_INTRBIT_TYPE { - MIF_STREAM_INTRBIT_TYPE_RESERVED, - MIF_STREAM_INTRBIT_TYPE_ALLOC, -}; - -/* Forward Decls */ - -struct mif_stream; - -/* Public Functions */ - -/** - * Initialises MIF Stream state. - */ -int mif_stream_init(struct mif_stream *stream, enum scsc_mif_abs_target target, enum MIF_STREAM_DIRECTION direction, uint32_t num_packets, uint32_t packet_size, - struct scsc_mx *mx, enum MIF_STREAM_INTRBIT_TYPE intrbit, mifintrbit_handler tohost_irq_handler, void *data); -/** - * Initialises MIF Output Stream state. - */ -void mif_stream_release(struct mif_stream *stream); -/** - * Reads the given number of bytes from the MIF stream, copying them - * to the provided address. This removes the read data from the stream. - * - * Returns the number of bytes read. - */ -uint32_t mif_stream_read(struct mif_stream *stream, void *buf, uint32_t num_bytes); - -/** - * Returns a pointer to the next packet of data within the stream, without - * removing it. This can be used to processss data in place without needing to - * copy it first. - * - * If multiple packets are present these can be read in turn by setting the value - * of current_packet to the returned value from the previous call to mif_stream_peek. - * Each time the returned pointer will advance in the stream by mif_stream_block_size() - * bytes. - * - * Callers cannot assume that multiple calls to mif_stream_peek() will return - * consecutive addresses. - * - * mif_stream_peek_complete must be called to remove the packet(s) from the stream. - * - * Returns a pointer to the beginning of the packet to read, or NULL if there is no - * packet to process. - * - * Example use: - * // Get the first data packet - * void *current_packet = mif_stream_peek( buffer, NULL ); - * void *last_packet = NULL; - * while( current_packet != NULL ) - * { - * // Process data packet - * ... - * - * // Get the next data packet - * last_packet = current_packet; - * current_packet = mif_stream_peek( buffer, current_packet ); - * } - * - * // Remove all processed packets from the stream - * if( last_packet != NULL ) - * { - * mif_stream_peek( buffer, last_packet ); - * } - */ -const void *mif_stream_peek(struct mif_stream *stream, const void *current_packet); - -/** - * Removes all packets from the stream up to and including the given - * packet. - * - * This must be called after using mif_stream_peek to indicate that packet(s) - * can be removed from the stream. - */ -void mif_stream_peek_complete(struct mif_stream *stream, const void *packet); - -/** - * Writes the given number of bytes to the MIF stream. - * - * Returns true if the block was written, false if there is not enough - * free space in the buffer for the data. - */ -bool mif_stream_write(struct mif_stream *stream, const void *buf, uint32_t num_bytes); - -/** - * Writes a set of non-contiguous data blocks to the MIF stream - * as a contiguous set. - * - * Returns true if the blocks were written, false if there is not enough - * free space in the buffer for the block. - */ -bool mif_stream_write_gather(struct mif_stream *stream, const void **bufs, uint32_t *lengths, uint32_t num_bufs); - -/** - * Returns the size in bytes of each individual block within the stream. - * - * When reading data from the stream using mif_stream_read or mif_stream_peek - * this value is the amount of data - */ -uint32_t mif_stream_block_size(struct mif_stream *stream); - -/** - * Returns the interrupt number that will be triggered by reads from the stream - */ -uint8_t mif_stream_read_interrupt(struct mif_stream *stream); - -/** - * Returns the interrupt number that will be triggered by writes to the stream - */ -uint8_t mif_stream_write_interrupt(struct mif_stream *stream); - -/* - * Initialises the stream's part of the configuration area - */ -void mif_stream_config_serialise(struct mif_stream *stream, struct mxstreamconf *stream_conf); - -/** - * Log the state of this stream at the specified log_level. - */ -void mif_stream_log(const struct mif_stream *stream, enum scsc_log_level log_level); - -/** - * MIF Packet Stream Descriptor. - */ -struct mif_stream { - struct scsc_mx *mx; - struct cpacketbuffer buffer; - - /** MIF stream peer, R4 or M4? */ - enum MIF_STREAM_PEER peer; - - /** MIF interrupt bit index, one in each direction */ - uint8_t read_bit_idx; - uint8_t write_bit_idx; - enum MIF_STREAM_DIRECTION direction; -}; - -#endif /* MIFSTREAM_H__ */ diff --git a/drivers/misc/samsung/scsc/mx140_clk.c b/drivers/misc/samsung/scsc/mx140_clk.c deleted file mode 100755 index 3ce350b747f8..000000000000 --- a/drivers/misc/samsung/scsc/mx140_clk.c +++ /dev/null @@ -1,799 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "scsc_mx_impl.h" - -#ifdef CONFIG_SCSC_CLK20MHZ_TEST -#include "mx140_clk_test.h" -#endif - -/* Note: define MX140_CLK_VERBOSE_CALLBACKS to get more callbacks when events occur. - * without this, the only callbacks are failure/success from request() - */ -static int auto_start; -module_param(auto_start, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(auto_start, "Start service automatically: Default 0: disabled, 1: Enabled"); - -static DEFINE_MUTEX(clk_lock); -static DEFINE_MUTEX(clk_work_lock); - -struct workqueue_struct *mx140_clk20mhz_wq; -struct work_struct mx140_clk20mhz_work; - -static int recovery; -static int recovery_pending_stop_close; -#define MX140_SERVICE_RECOVERY_TIMEOUT 20000 - -/* Static Singleton */ -static struct mx140_clk20mhz { - /* scsc_service_client has to be the first */ - struct scsc_service_client mx140_clk20mhz_service_client; - struct scsc_service *mx140_clk20mhz_service; - struct scsc_mx *mx; - - atomic_t clk_request; - atomic_t maxwell_is_present; - atomic_t mx140_clk20mhz_service_started; - atomic_t request_pending; - atomic_t mx140_clk20mhz_service_failed; - - void *data; - void (*mx140_clk20mhz_client_cb)(void *data, enum mx140_clk20mhz_status event); - - struct proc_dir_entry *procfs_ctrl_dir; - u32 procfs_ctrl_dir_num; - - struct wake_lock clk_wake_lock; - struct completion recovery_probe_completion; - -} clk20mhz; - -static void mx140_clk20mhz_wq_stop(void); -static int mx140_clk20mhz_stop_service(struct scsc_mx *mx); - -#ifndef AID_MXPROC -#define AID_MXPROC 0 -#endif - -static void mx140_clk20mhz_restart(void); - -#define MX_CLK20_DIRLEN 128 -static const char *procdir_ctrl = "driver/mx140_clk"; -static u32 proc_count; - -/* Framework for registering proc handlers */ -#define MX_CLK20_PROCFS_RW_FILE_OPS(name) \ - static ssize_t mx_procfs_ ## name ## _write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); \ - static ssize_t mx_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations mx_procfs_ ## name ## _fops = { \ - .read = mx_procfs_ ## name ## _read, \ - .write = mx_procfs_ ## name ## _write, \ - .open = mx_clk20_procfs_generic_open, \ - .llseek = generic_file_llseek \ - } -#define MX_CLK20_PROCFS_RO_FILE_OPS(name) \ - static ssize_t mx_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations mx_procfs_ ## name ## _fops = { \ - .read = mx_procfs_ ## name ## _read, \ - .open = mx_clk20_procfs_generic_open, \ - .llseek = generic_file_llseek \ - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MX_PDE_DATA(inode) PDE_DATA(inode) -#else -#define MX_PDE_DATA(inode) (PDE(inode)->data) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MX_CLK20_PROCFS_SET_UID_GID(_entry) \ - do { \ - kuid_t proc_kuid = KUIDT_INIT(AID_MXPROC); \ - kgid_t proc_kgid = KGIDT_INIT(AID_MXPROC); \ - proc_set_user(_entry, proc_kuid, proc_kgid); \ - } while (0) -#else -#define MX_CLK20_PROCFS_SET_UID_GID(entry) \ - do { \ - (entry)->uid = AID_MXPROC; \ - (entry)->gid = AID_MXPROC; \ - } while (0) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MX_CLK20_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry = proc_create_data(# name, mode, parent, &mx_procfs_ ## name ## _fops, _sdev); \ - MX_CLK20_PROCFS_SET_UID_GID(entry); \ - } while (0) -#else -#define MX_CLK20_PROCFS_ADD_FILE(_data, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = create_proc_entry(# name, mode, parent); \ - if (entry) { \ - entry->proc_fops = &mx_procfs_ ## name ## _fops; \ - entry->data = _data; \ - MX_CLK20_PROCFS_SET_UID_GID(entry); \ - } \ - } while (0) -#endif - -#define MX_CLK20_PROCFS_REMOVE_FILE(name, parent) remove_proc_entry(# name, parent) - -/* Open handler */ -static int mx_clk20_procfs_generic_open(struct inode *inode, struct file *file) -{ - file->private_data = MX_PDE_DATA(inode); - return 0; -} - -/* No-op */ -static ssize_t mx_procfs_restart_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - (void)user_buf; - (void)count; - (void)ppos; - - return 0; -} - -/* Restart clock service */ -static ssize_t mx_procfs_restart_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - (void)file; - (void)user_buf; - (void)ppos; - - mx140_clk20mhz_restart(); - - SCSC_TAG_INFO(MX_PROC, "OK\n"); - return count; -} - -/* Register proc handler */ -MX_CLK20_PROCFS_RW_FILE_OPS(restart); - -/* Populate proc node */ -static int mx140_clk20mhz_create_ctrl_proc_dir(struct mx140_clk20mhz *clk20mhz) -{ - char dir[MX_CLK20_DIRLEN]; - struct proc_dir_entry *parent; - - (void)snprintf(dir, sizeof(dir), "%s%d", procdir_ctrl, proc_count); - parent = proc_mkdir(dir, NULL); - if (!parent) { - SCSC_TAG_ERR(MX_PROC, "failed to create proc dir %s\n", procdir_ctrl); - return -EINVAL; - } -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = clk20mhz; -#endif - clk20mhz->procfs_ctrl_dir = parent; - clk20mhz->procfs_ctrl_dir_num = proc_count; - MX_CLK20_PROCFS_ADD_FILE(clk20mhz, restart, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SCSC_TAG_DEBUG(MX_PROC, "created %s proc dir\n", dir); - proc_count++; - - return 0; -} - -/* Remove proc node */ -static void mx140_clk20mhz_remove_ctrl_proc_dir(struct mx140_clk20mhz *clk20mhz) -{ - if (clk20mhz->procfs_ctrl_dir) { - char dir[MX_CLK20_DIRLEN]; - - MX_CLK20_PROCFS_REMOVE_FILE(restart, clk20mhz->procfs_ctrl_dir); - (void)snprintf(dir, sizeof(dir), "%s%d", procdir_ctrl, clk20mhz->procfs_ctrl_dir_num); - remove_proc_entry(dir, NULL); - clk20mhz->procfs_ctrl_dir = NULL; - proc_count--; - SCSC_TAG_DEBUG(MX_PROC, "removed %s proc dir\n", dir); - } -} - -/* Maxwell manager has detected a recoverable issue no action needed */ -static u8 mx140_clk20mhz_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void) client; - SCSC_TAG_INFO(CLK20, "\n"); - return err->level; -} - -/* Maxwell manager has detected an issue and the service should freeze */ -static bool mx140_clk20mhz_stop_on_failure(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void) err; - atomic_set(&clk20mhz.mx140_clk20mhz_service_failed, 1); - - mutex_lock(&clk_work_lock); - recovery = 1; - reinit_completion(&clk20mhz.recovery_probe_completion); - mutex_unlock(&clk_work_lock); - -#ifdef MX140_CLK_VERBOSE_CALLBACKS - /* If call back is registered, inform the user about an asynchronous failure */ - if (clk20mhz.mx140_clk20mhz_client_cb) - clk20mhz.mx140_clk20mhz_client_cb(clk20mhz.data, MX140_CLK_ASYNC_FAIL); -#endif - - SCSC_TAG_INFO(CLK20, "\n"); - - return false; -} - -/* Maxwell manager has handled a failure and the chip has been resat. */ -static void mx140_clk20mhz_failure_reset(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code) -{ - (void)level; - (void)scsc_syserr_code; - atomic_set(&clk20mhz.mx140_clk20mhz_service_failed, 1); - -#ifdef MX140_CLK_VERBOSE_CALLBACKS - /* If call back is registered, inform the user about an asynchronous failure */ - if (clk20mhz.mx140_clk20mhz_client_cb) - clk20mhz.mx140_clk20mhz_client_cb(clk20mhz.data, MX140_CLK_ASYNC_FAIL); -#endif - SCSC_TAG_INFO(CLK20, "\n"); -} - -static int mx140_clk20mhz_start_service(struct scsc_mx *mx) -{ - int r; - - /* Open the service and get resource pointers */ - clk20mhz.mx140_clk20mhz_service = scsc_mx_service_open(mx, SCSC_SERVICE_ID_CLK20MHZ, &clk20mhz.mx140_clk20mhz_service_client, &r); - if (!clk20mhz.mx140_clk20mhz_service) { - SCSC_TAG_ERR(CLK20, "scsc_mx_service_open failed %d\n", r); - return r; - } - - /* In case of recovery ensure WLBT has ownership */ - if (atomic_read(&clk20mhz.mx140_clk20mhz_service_failed)) { - struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(clk20mhz.mx); - - if (!mif) - goto error; - - if (mif->mif_restart) - mif->mif_restart(mif); - - atomic_set(&clk20mhz.mx140_clk20mhz_service_failed, 0); - } - - /* Start service. Will bring-up the chip if the chip is disabled */ - if (scsc_mx_service_start(clk20mhz.mx140_clk20mhz_service, 0)) { - SCSC_TAG_ERR(CLK20, "scsc_mx_service_start failed\n"); - goto error; - } - - atomic_set(&clk20mhz.mx140_clk20mhz_service_started, 1); - - /* If call back is registered, inform the user that the service has started */ - if (atomic_read(&clk20mhz.clk_request) && clk20mhz.mx140_clk20mhz_client_cb) - clk20mhz.mx140_clk20mhz_client_cb(clk20mhz.data, MX140_CLK_STARTED); - - return 0; -error: - return -EIO; -} - -static int mx140_clk20mhz_stop_service(struct scsc_mx *mx) -{ - int r; - - if (!atomic_read(&clk20mhz.mx140_clk20mhz_service_started)) { - SCSC_TAG_INFO(CLK20, "Service not started\n"); - return -ENODEV; - } - - /* Stop service. */ - if (scsc_mx_service_stop(clk20mhz.mx140_clk20mhz_service)) { - SCSC_TAG_ERR(CLK20, "scsc_mx_service_stop failed\n"); -#ifdef MX140_CLK_VERBOSE_CALLBACKS - /* If call back is registered, inform the user that the service has failed to stop */ - if (clk20mhz.mx140_clk20mhz_client_cb) - clk20mhz.mx140_clk20mhz_client_cb(clk20mhz.data, MX140_CLK_NOT_STOPPED); - return -EIO; -#endif - } - - /* Ignore a service_stop timeout above as it's better to try to close */ - - /* Close service, if no other service is using Maxwell, chip will turn off */ - r = scsc_mx_service_close(clk20mhz.mx140_clk20mhz_service); - if (r) { - SCSC_TAG_ERR(CLK20, "scsc_mx_service_close failed\n"); - -#ifdef MX140_CLK_VERBOSE_CALLBACKS - /* If call back is registered, inform the user that the service has failed to close */ - if (clk20mhz.mx140_clk20mhz_client_cb) - clk20mhz.mx140_clk20mhz_client_cb(clk20mhz.data, MX140_CLK_NOT_STOPPED); - return -EIO; -#endif - } - - atomic_set(&clk20mhz.mx140_clk20mhz_service_started, 0); - -#ifdef MX140_CLK_VERBOSE_CALLBACKS - /* If call back is registered, inform the user that the service has stopped */ - if (clk20mhz.mx140_clk20mhz_client_cb) - clk20mhz.mx140_clk20mhz_client_cb(clk20mhz.data, MX140_CLK_STOPPED); -#endif - return 0; -} - -#define MX140_CLK_TRIES (20) - -static void mx140_clk20mhz_work_func(struct work_struct *work) -{ - int i; - int r = 0; - enum mx140_clk20mhz_status status; - - mutex_lock(&clk_work_lock); - - for (i = 0; i < MX140_CLK_TRIES; i++) { - if (atomic_read(&clk20mhz.clk_request) == 0) { - SCSC_TAG_INFO(CLK20, "mx140_clk20mhz_start_service no longer requested\n"); - recovery = 0; - mutex_unlock(&clk_work_lock); - return; - } - - SCSC_TAG_INFO(CLK20, "Calling mx140_clk20mhz_start_service\n"); - r = mx140_clk20mhz_start_service(clk20mhz.mx); - switch (r) { - case 0: - SCSC_TAG_INFO(CLK20, "mx140_clk20mhz_start_service OK\n"); - recovery = 0; - mutex_unlock(&clk_work_lock); - return; - case -EAGAIN: - SCSC_TAG_INFO(CLK20, "FW not found because filesystem not mounted yet, retrying...\n"); - msleep(500); /* No FS yet, retry */ - break; - default: - SCSC_TAG_INFO(CLK20, "mx140_clk20mhz_start_service failed %d\n", r); - goto err; - } - } -err: - SCSC_TAG_ERR(CLK20, "Unable to start the 20MHz clock service\n"); - - /* Deferred service start failure or timeout. - * We assume it'll never manage to start - e.g. bad or missing f/w. - */ - if (r) { - struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(clk20mhz.mx); - - SCSC_TAG_ERR(CLK20, "Deferred start timeout (%d)\n", r); - atomic_set(&clk20mhz.mx140_clk20mhz_service_failed, 1); - - /* Switch USBPLL ownership to AP so USB may be used */ - if (mif && mif->mif_cleanup) - mif->mif_cleanup(mif); - } - - /* If call back is registered, inform the user that the service has failed to start */ - if (atomic_read(&clk20mhz.clk_request) && clk20mhz.mx140_clk20mhz_client_cb) { - /* The USB/PLL driver has inadequate error handing... - * Lie that the start was successful when AP has control - */ - status = atomic_read(&clk20mhz.mx140_clk20mhz_service_failed) ? MX140_CLK_STARTED : MX140_CLK_NOT_STARTED; - - /* Also lie that the start was successful when the mx140 driver is halted after f/w panic */ - if (r == -EILSEQ || r == -EPERM) - status = MX140_CLK_STARTED; - - SCSC_TAG_INFO(CLK20, "cb %d\n", status); - clk20mhz.mx140_clk20mhz_client_cb(clk20mhz.data, status); - } - recovery = 0; - mutex_unlock(&clk_work_lock); -} - -static void mx140_clk20mhz_wq_init(void) -{ - mx140_clk20mhz_wq = create_singlethread_workqueue("mx140_clk20mhz_wq"); - INIT_WORK(&mx140_clk20mhz_work, mx140_clk20mhz_work_func); -} - -static void mx140_clk20mhz_wq_stop(void) -{ - cancel_work_sync(&mx140_clk20mhz_work); - flush_workqueue(mx140_clk20mhz_wq); -} - -static void mx140_clk20mhz_wq_deinit(void) -{ - mx140_clk20mhz_wq_stop(); - destroy_workqueue(mx140_clk20mhz_wq); -} - -static void mx140_clk20mhz_wq_start(void) -{ - queue_work(mx140_clk20mhz_wq, &mx140_clk20mhz_work); -} - -/* Register a callback function to indicate to the (USB) client the status of - * the clock request - */ -int mx140_clk20mhz_register(void (*client_cb)(void *data, enum mx140_clk20mhz_status event), void *data) -{ - SCSC_TAG_INFO(CLK20, "cb %p, %p\n", client_cb, data); - - mutex_lock(&clk_lock); - if (clk20mhz.mx140_clk20mhz_client_cb == NULL) { - SCSC_TAG_INFO(CLK20, "clk20Mhz client registered\n"); - clk20mhz.mx140_clk20mhz_client_cb = client_cb; - clk20mhz.data = data; - mutex_unlock(&clk_lock); - return 0; - } - - SCSC_TAG_ERR(CLK20, "clk20Mhz client already registered\n"); - mutex_unlock(&clk_lock); - return -EEXIST; -} -EXPORT_SYMBOL(mx140_clk20mhz_register); - -/* Unregister callback function */ -void mx140_clk20mhz_unregister(void) -{ - SCSC_TAG_INFO(CLK20, "\n"); - - mutex_lock(&clk_lock); - if (clk20mhz.mx140_clk20mhz_client_cb == NULL) { - SCSC_TAG_INFO(CLK20, "clk20Mhz client not registered\n"); - mutex_unlock(&clk_lock); - return; - } - - clk20mhz.mx140_clk20mhz_client_cb = NULL; - clk20mhz.data = NULL; - mutex_unlock(&clk_lock); -} -EXPORT_SYMBOL(mx140_clk20mhz_unregister); - -/* Indicate that an external client requires mx140's 20 MHz clock. - * The Core driver will boot mx140 as required and ensure that the - * clock remains running. - * - * If a callback was installed by register(), do this asynchronously. - */ -int mx140_clk20mhz_request(void) -{ - mutex_lock(&clk_lock); - atomic_inc(&clk20mhz.clk_request); - - SCSC_TAG_INFO(CLK20, "%d\n", atomic_read(&clk20mhz.clk_request)); - - if (!atomic_read(&clk20mhz.maxwell_is_present)) { - SCSC_TAG_INFO(CLK20, "Maxwell is not present yet, store request\n"); - atomic_set(&clk20mhz.request_pending, 1); - mutex_unlock(&clk_lock); - return 0; - } - - if (recovery) { - int r; - - mutex_unlock(&clk_lock); - r = wait_for_completion_timeout(&clk20mhz.recovery_probe_completion, - msecs_to_jiffies(MX140_SERVICE_RECOVERY_TIMEOUT)); - mutex_lock(&clk_lock); - if (r == 0) { - SCSC_TAG_INFO(CLK20, "recovery_probe_completion timeout - try a start\n"); - mx140_clk20mhz_wq_start(); - } - } else if (!atomic_read(&clk20mhz.mx140_clk20mhz_service_started)) - mx140_clk20mhz_wq_start(); - else - SCSC_TAG_INFO(CLK20, "Service already started\n"); - - mutex_unlock(&clk_lock); - return 0; -} -EXPORT_SYMBOL(mx140_clk20mhz_request); - -/* Indicate that an external client no requires mx140's 20 MHz clock - * The Core driver will shut down mx140 if no other services are - * currently running - * - * If a callback was installed by register(), do this asynchronously. - */ -int mx140_clk20mhz_release(void) -{ - int ret = 0; - - mutex_lock(&clk_lock); - atomic_dec(&clk20mhz.clk_request); - SCSC_TAG_INFO(CLK20, "%d\n", atomic_read(&clk20mhz.clk_request)); - - if (!atomic_read(&clk20mhz.maxwell_is_present)) { - SCSC_TAG_INFO(CLK20, "Maxwell is released before probe\n"); - if (!atomic_read(&clk20mhz.request_pending)) { - SCSC_TAG_INFO(CLK20, "Maxwell had request pending. Cancel it\n"); - atomic_set(&clk20mhz.request_pending, 0); - } - mutex_unlock(&clk_lock); - return 0; - } - - /* Cancel any pending attempt */ - mx140_clk20mhz_wq_stop(); - - if (recovery) { - recovery_pending_stop_close = 1; - } else { - ret = mx140_clk20mhz_stop_service(clk20mhz.mx); - if (ret == -ENODEV) { - /* Suppress error if it wasn't running */ - ret = 0; - } - } - - /* Suppress stop failure if the service is failed */ - if (atomic_read(&clk20mhz.mx140_clk20mhz_service_failed)) { - SCSC_TAG_INFO(CLK20, "Return OK as control is with AP\n"); - atomic_set(&clk20mhz.mx140_clk20mhz_service_started, 0); - ret = 0; - } - - mutex_unlock(&clk_lock); - return ret; -} -EXPORT_SYMBOL(mx140_clk20mhz_release); - -/* Probe callback after platform driver is registered */ -void mx140_clk20mhz_probe(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - SCSC_TAG_INFO(CLK20, "\n"); - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery) { - SCSC_TAG_INFO(CLK20, "Ignore probe - no recovery in progress\n"); - return; - } - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && recovery) { - SCSC_TAG_INFO(CLK20, "Recovery probe\n"); - - /** - * If recovery_pending_stop_close is set, then there was a stop - * during recovery (could be due to USB cable unplugged) so - * recovery should just stop here. - * The mx140_clk service has been closed in the remove callback. - */ - mutex_lock(&clk_lock); - if (recovery_pending_stop_close) { - SCSC_TAG_INFO(CLK20, "Recovery probe - stop during recovery, so don't recover\n"); - recovery_pending_stop_close = 0; - recovery = 0; - mutex_unlock(&clk_lock); - /** - * Should there have been a new start request during - * recovery (very unlikely), then the complete timeout - * will ensure that a start is requested. - */ - return; - } - mutex_unlock(&clk_lock); - - mutex_lock(&clk_work_lock); - mx140_clk20mhz_wq_start(); - mutex_unlock(&clk_work_lock); - complete_all(&clk20mhz.recovery_probe_completion); - } else { - SCSC_TAG_INFO(CLK20, "Maxwell probed\n"); - clk20mhz.mx = mx; - clk20mhz.mx140_clk20mhz_service_client.failure_notification = mx140_clk20mhz_failure_notification; - clk20mhz.mx140_clk20mhz_service_client.stop_on_failure_v2 = mx140_clk20mhz_stop_on_failure; - clk20mhz.mx140_clk20mhz_service_client.failure_reset_v2 = mx140_clk20mhz_failure_reset; - - mx140_clk20mhz_create_ctrl_proc_dir(&clk20mhz); - - mx140_clk20mhz_wq_init(); - - atomic_set(&clk20mhz.maxwell_is_present, 1); - - mutex_lock(&clk_work_lock); - if ((auto_start || atomic_read(&clk20mhz.request_pending))) { - atomic_set(&clk20mhz.request_pending, 0); - SCSC_TAG_INFO(CLK20, "start pending service\n"); - mx140_clk20mhz_wq_start(); - } - mutex_unlock(&clk_work_lock); - } -} - - -static void mx140_clk20mhz_restart(void) -{ - int r; - struct scsc_mif_abs *mif; - - SCSC_TAG_INFO(CLK20, "\n"); - - wake_lock(&clk20mhz.clk_wake_lock); - - mutex_lock(&clk_lock); - - if (!atomic_read(&clk20mhz.mx140_clk20mhz_service_started)) { - SCSC_TAG_INFO(CLK20, "service wasn't started\n"); - goto done; - } - - mif = scsc_mx_get_mif_abs(clk20mhz.mx); - if (mif == NULL) - goto done; - - /* Don't stop the 20 MHz clock service. Leave it running until - * WLBT resets due to the service_close(). - */ - - /* Ensure USBPLL is running and owned by AP, to stop USB disconnect */ - if (mif->mif_cleanup) - mif->mif_cleanup(mif); - - r = scsc_mx_service_close(clk20mhz.mx140_clk20mhz_service); - if (r) { - SCSC_TAG_ERR(CLK20, "scsc_mx_service_close failed (%d)\n", r); - goto done; - } - - /* ...and restart the 20 MHz clock service */ - clk20mhz.mx140_clk20mhz_service = scsc_mx_service_open(clk20mhz.mx, SCSC_SERVICE_ID_CLK20MHZ, &clk20mhz.mx140_clk20mhz_service_client, &r); - if (clk20mhz.mx140_clk20mhz_service == NULL) { - SCSC_TAG_ERR(CLK20, "reopen failed %d\n", r); - atomic_set(&clk20mhz.mx140_clk20mhz_service_started, 0); - goto done; - } - - /* Ensure USBPLL is owned by WLBT again */ - if (mif->mif_restart) - mif->mif_restart(mif); - - r = scsc_mx_service_start(clk20mhz.mx140_clk20mhz_service, 0); - if (r) { - SCSC_TAG_ERR(CLK20, "restart failed %d\n", r); - r = scsc_mx_service_close(clk20mhz.mx140_clk20mhz_service); - if (r) - SCSC_TAG_ERR(CLK20, "scsc_mx_service_close failed %d\n", r); - atomic_set(&clk20mhz.mx140_clk20mhz_service_started, 0); - goto done; - } - - SCSC_TAG_INFO(CLK20, "restarted\n"); -done: - mutex_unlock(&clk_lock); - wake_unlock(&clk20mhz.clk_wake_lock); -} - -/* Remove callback platform driver is unregistered */ -void mx140_clk20mhz_remove(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - int r; - - mutex_lock(&clk_work_lock); - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery) { - SCSC_TAG_INFO(CLK20, "Ignore recovery remove: Service driver not active\n"); - goto done; - } else if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && recovery) { - struct scsc_mif_abs *mif; - - SCSC_TAG_INFO(CLK20, "Recovery remove\n"); - - mutex_lock(&clk_lock); - mx140_clk20mhz_wq_stop(); - - mif = scsc_mx_get_mif_abs(clk20mhz.mx); - if (mif == NULL) - goto done_local; - - /** - * If there's been a stop during recovery ensure that the - * mx140_clk service is closed in the mx driver, but do not - * touch USBPLL ownership since this will already have been - * handled. - */ - if (!recovery_pending_stop_close) { - /* Don't stop the clock service - leave it running until - * service_close() resets WLBT. - */ - - /* Switch ownership of USBPLL to the AP. Ownership - * returns to WLBT after recovery completes. - */ - if (mif->mif_cleanup) - mif->mif_cleanup(mif); - } - - r = scsc_mx_service_close(clk20mhz.mx140_clk20mhz_service); - if (r) - SCSC_TAG_INFO(CLK20, "scsc_mx_service_close failed %d\n", r); - - atomic_set(&clk20mhz.mx140_clk20mhz_service_started, 0); -done_local: - mutex_unlock(&clk_lock); - } else { - SCSC_TAG_INFO(CLK20, "Maxwell removed\n"); - mx140_clk20mhz_remove_ctrl_proc_dir(&clk20mhz); - atomic_set(&clk20mhz.maxwell_is_present, 0); - mx140_clk20mhz_wq_deinit(); - } - -done: - mutex_unlock(&clk_work_lock); -} - -/* 20MHz client driver */ -struct scsc_mx_module_client mx140_clk20mhz_driver = { - .name = "MX 20MHz clock client", - .probe = mx140_clk20mhz_probe, - .remove = mx140_clk20mhz_remove, -}; - -/* 20MHz service driver initialization */ -static int __init mx140_clk20mhz_init(void) -{ - int ret; - - SCSC_TAG_INFO(CLK20, "Registering service\n"); - - wake_lock_init(&clk20mhz.clk_wake_lock, WAKE_LOCK_SUSPEND, "clk20_wl"); - init_completion(&clk20mhz.recovery_probe_completion); - - atomic_set(&clk20mhz.clk_request, 0); - atomic_set(&clk20mhz.maxwell_is_present, 0); - atomic_set(&clk20mhz.mx140_clk20mhz_service_started, 0); - atomic_set(&clk20mhz.request_pending, 0); - atomic_set(&clk20mhz.mx140_clk20mhz_service_failed, 0); - - /* Register with Maxwell Framework */ - ret = scsc_mx_module_register_client_module(&mx140_clk20mhz_driver); - if (ret) { - SCSC_TAG_ERR(CLK20, "scsc_mx_module_register_client_module failed: r=%d\n", ret); - return ret; - } - -#ifdef CONFIG_SCSC_CLK20MHZ_TEST - mx140_clk_test_init(); -#endif - return 0; -} - -static void __exit mx140_clk20mhz_exit(void) -{ - scsc_mx_module_unregister_client_module(&mx140_clk20mhz_driver); -#ifdef CONFIG_SCSC_CLK20MHZ_TEST - mx140_clk_test_exit(); -#endif - - complete_all(&clk20mhz.recovery_probe_completion); - wake_lock_destroy(&clk20mhz.clk_wake_lock); -} - -module_init(mx140_clk20mhz_init); -module_exit(mx140_clk20mhz_exit); - -MODULE_DESCRIPTION("Samsung Maxwell 20MHz Clock Service"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/misc/samsung/scsc/mx140_clk_test.c b/drivers/misc/samsung/scsc/mx140_clk_test.c deleted file mode 100644 index 858efb1fd362..000000000000 --- a/drivers/misc/samsung/scsc/mx140_clk_test.c +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include "scsc_mx_impl.h" - -/* char device entry declarations */ -static dev_t mx140_clk_test_dev_t; -static struct class *mx140_clk_test_class; -static struct cdev *mx140_clk_test_cdev; - -/* Call back function registered with 20MHz clock framework */ -static void client_cb(void *data, enum mx140_clk20mhz_status event) -{ - switch (event) { - case MX140_CLK_STARTED: - SCSC_TAG_INFO(CLK20_TEST, "Event MX140_CLK_STARTED received\n"); - break; - case MX140_CLK_STOPPED: - SCSC_TAG_INFO(CLK20_TEST, "Event MX140_CLK_STOPPED received\n"); - break; - case MX140_CLK_NOT_STARTED: - SCSC_TAG_INFO(CLK20_TEST, "Event MX140_CLK_NOT_STARTED received\n"); - break; - case MX140_CLK_NOT_STOPPED: - SCSC_TAG_INFO(CLK20_TEST, "Event MX140_CLK_NOT_STOPPED received\n"); - break; - case MX140_CLK_ASYNC_FAIL: - SCSC_TAG_INFO(CLK20_TEST, "Event MX140_CLK_ASYNC_FAIL received\n"); - break; - default: - break; - } -} - -static int mx140_clk_test_dev_open(struct inode *inode, struct file *file) -{ - mx140_clk20mhz_register(client_cb, NULL); - return 0; -} - -static int mx140_clk_test_dev_release(struct inode *inode, struct file *file) -{ - mx140_clk20mhz_unregister(); - return 0; -} - - -static ssize_t mx140_clk_test_dev_write(struct file *file, const char *data, size_t len, loff_t *offset) -{ - unsigned long count; - char str[2]; /* One value and carry return */ - long int val = 0; - - if (len > 2) { - SCSC_TAG_ERR(CLK20_TEST, "Incorrect value len %zd\n", len); - goto error; - } - - count = copy_from_user(str, data, len); - - str[1] = 0; - - if (kstrtol(str, 10, &val)) { - SCSC_TAG_ERR(CLK20_TEST, "Invalid value\n"); - goto error; - } - - if (val == 1) - mx140_clk20mhz_request(); - else if (val == 0) - mx140_clk20mhz_release(); - else - SCSC_TAG_INFO(CLK20_TEST, "val %ld is not valid, 1 - on, 0 - off\n", val); -error: - return len; -} - -static ssize_t mx140_clk_test_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) -{ - return length; -} - -static const struct file_operations mx140_clk_test_dev_fops = { - .owner = THIS_MODULE, - .open = mx140_clk_test_dev_open, - .read = mx140_clk_test_dev_read, - .write = mx140_clk_test_dev_write, - .release = mx140_clk_test_dev_release, -}; - -/* 20MHz service driver registration */ -void mx140_clk_test_init(void) -{ - int ret; - - SCSC_TAG_INFO(CLK20_TEST, "Registering mx140 TEST\n"); - - ret = alloc_chrdev_region(&mx140_clk_test_dev_t, 0, 1, "mx140_clk_test-cdev"); - if (ret < 0) { - SCSC_TAG_ERR(CLK20_TEST, "failed to alloc chrdev region\n"); - goto fail_alloc_chrdev_region; - } - - mx140_clk_test_cdev = cdev_alloc(); - if (!mx140_clk_test_cdev) { - ret = -ENOMEM; - SCSC_TAG_ERR(CLK20_TEST, "failed to alloc cdev\n"); - goto fail_alloc_cdev; - } - - cdev_init(mx140_clk_test_cdev, &mx140_clk_test_dev_fops); - ret = cdev_add(mx140_clk_test_cdev, mx140_clk_test_dev_t, 1); - if (ret < 0) { - SCSC_TAG_ERR(CLK20_TEST, "failed to add cdev\n"); - goto fail_add_cdev; - } - - mx140_clk_test_class = class_create(THIS_MODULE, "mx140_clk_test"); - if (!mx140_clk_test_class) { - ret = -EEXIST; - SCSC_TAG_ERR(CLK20_TEST, "failed to create class\n"); - goto fail_create_class; - } - - if (!device_create(mx140_clk_test_class, NULL, mx140_clk_test_dev_t, NULL, "mx140_usb_clk_test_%d", MINOR(mx140_clk_test_dev_t))) { - ret = -EINVAL; - SCSC_TAG_ERR(CLK20_TEST, "failed to create device\n"); - goto fail_create_device; - } - - return; -fail_create_device: - class_destroy(mx140_clk_test_class); -fail_create_class: - cdev_del(mx140_clk_test_cdev); -fail_add_cdev: -fail_alloc_cdev: - unregister_chrdev_region(mx140_clk_test_dev_t, 1); -fail_alloc_chrdev_region: - return; -} - -void mx140_clk_test_exit(void) -{ - device_destroy(mx140_clk_test_class, mx140_clk_test_dev_t); - class_destroy(mx140_clk_test_class); - cdev_del(mx140_clk_test_cdev); - unregister_chrdev_region(mx140_clk_test_dev_t, 1); -} diff --git a/drivers/misc/samsung/scsc/mx140_clk_test.h b/drivers/misc/samsung/scsc/mx140_clk_test.h deleted file mode 100644 index c51fe2f9ac04..000000000000 --- a/drivers/misc/samsung/scsc/mx140_clk_test.h +++ /dev/null @@ -1,13 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MX140_CLK_TEST_H__ -#define __MX140_CLK_TEST_H___ - - -void mx140_clk_test_init(void); -void mx140_clk_test_exit(void); -#endif /* __MX140_CLK_TEST_H___*/ diff --git a/drivers/misc/samsung/scsc/mx140_file.c b/drivers/misc/samsung/scsc/mx140_file.c deleted file mode 100644 index 3df437ef60fc..000000000000 --- a/drivers/misc/samsung/scsc/mx140_file.c +++ /dev/null @@ -1,652 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#include -#include -#include -#include -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE -#include -#else -#include -#endif -#include -#include - -#include -#include - -#include "scsc_mx_impl.h" - -/* Firmware directory definitions */ - -#define SCSC_MULTI_RF_CHIP_ID /* Select FW by RF chip ID, not rev */ - -#if defined(CONFIG_SCSC_CORE_FW_LOCATION) && !defined(CONFIG_SCSC_CORE_FW_LOCATION_AUTO) -#define MX140_FW_BASE_DIR_SYSTEM_ETC_WIFI CONFIG_SCSC_CORE_FW_LOCATION -#define MX140_FW_BASE_DIR_VENDOR_ETC_WIFI CONFIG_SCSC_CORE_FW_LOCATION -#else -#define MX140_FW_BASE_DIR_SYSTEM_ETC_WIFI "/system/etc/wifi" -#define MX140_FW_BASE_DIR_VENDOR_ETC_WIFI "/vendor/etc/wifi" -#endif - -/* Look for this file in /etc/wifi */ -#ifdef CONFIG_ANDROID -#define MX140_FW_DETECT "mx" -#else -/* Linux host vfs_stat() doesn't find mx* with "mx" */ -#define MX140_FW_DETECT "mx140.bin" -#endif - -/* Paths for vendor utilities, used when CONFIG_SCSC_CORE_FW_LOCATION_AUTO=n */ -#define MX140_EXE_DIR_VENDOR "/vendor/bin" /* Oreo */ -#define MX140_EXE_DIR_SYSTEM "/system/bin" /* Before Oreo */ - -#define MX140_FW_CONF_SUBDIR "conf" -#define MX140_FW_DEBUG_SUBDIR "debug" -#define MX140_FW_BIN "mx140.bin" -#define MX140_FW_PATH_MAX_LENGTH (512) - -#define MX140_FW_VARIANT_DEFAULT "mx140" - -/* Table of suffixes to append to f/w name */ -struct fw_suffix { - char suffix[6]; - u32 hw_ver; -}; - -#ifdef SCSC_MULTI_RF_CHIP_ID /* Select by chip ID (S611, S612) */ - -/* This scheme has one firmware binary for all revisions of an - * RF chip ID. - */ - -/* Table of known RF h/w IDs */ -static const struct fw_suffix fw_suffixes[] = { - { .suffix = "", .hw_ver = 0xff, }, /* plain mx140.bin, always used if found */ - { .suffix = "_s612", .hw_ver = 0xb1, }, - { .suffix = "_s611", .hw_ver = 0xb0, }, -}; - -#else /* Select by chip revision (EVT0.0, EVT0.1) */ - -/* This legacy scheme assumes a different fw binary for each revision - * of an RF chip ID, and those will uniquely identify the - * right build. This was used for early S5E7570 until a unified - * binary was available. - */ - -/* Table of known RF h/w revs */ -static const struct fw_suffix fw_suffixes[] = { - { .suffix = "_11", .hw_ver = 0x11, }, - { .suffix = "_10", .hw_ver = 0x10, }, - { .suffix = "_00", .hw_ver = 0x00, }, - { .suffix = "", .hw_ver = 0xff, }, /* plain mx140.bin, must be last */ -}; -#endif - -/* Once set, we always load this firmware suffix */ -static int fw_suffix_found = -1; - -/* Variant of firmware binary to load */ -static char *firmware_variant = MX140_FW_VARIANT_DEFAULT; -module_param(firmware_variant, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(firmware_variant, "mx140 firmware variant, default mx140"); - -/* RF hardware version of firmware to load. If "auto" this gets replaced with - * the suffix of FW that got loaded. - * If "manual" it loads the version specified by firmware_variant, verbatim. - */ -static char *firmware_hw_ver = "auto"; -module_param(firmware_hw_ver, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(firmware_hw_ver, "mx140 hw version detect, manual=disable"); - -/* FW base dir readable by usermode script */ -#ifdef CONFIG_SCSC_CORE_FW_LOCATION_AUTO -static char *fw_base_dir; -#else -static char *fw_base_dir = CONFIG_SCSC_CORE_FW_LOCATION; -#endif -module_param_named(base_dir, fw_base_dir, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(base_dir, "WLBT FW base directory"); - -/* Firmware and tool (moredump) exe base directory */ -#ifdef CONFIG_SCSC_CORE_FW_LOCATION_AUTO -static char base_dir[MX140_FW_PATH_MAX_LENGTH]; /* auto detect */ -static char exe_dir[MX140_FW_PATH_MAX_LENGTH]; /* auto detect */ -#else -static char base_dir[] = CONFIG_SCSC_CORE_FW_LOCATION; /* fixed in defconfig */ -static char exe_dir[] = CONFIG_SCSC_CORE_TOOL_LOCATION; /* fixed in defconfig */ -#endif - - -static bool enable_auto_sense; -module_param(enable_auto_sense, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_auto_sense, "deprecated"); - -static bool use_new_fw_structure = true; -module_param(use_new_fw_structure, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(use_new_fw_structure, "deprecated"); - -static char *cfg_platform = "default"; -module_param(cfg_platform, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(cfg_platform, "HCF config subdirectory"); - -/* Reads a configuration file into memory (f/w profile specific) */ -static int __mx140_file_request_conf(struct scsc_mx *mx, - const struct firmware **conf, - const char *platform_dir, - const char *config_rel_path, - const char *filename, - const bool flat) - -{ - char config_path[MX140_FW_PATH_MAX_LENGTH]; - int r; - - if (mx140_basedir_file(mx)) - return -ENOENT; - - if (flat) { - /* e.g. /etc/wifi/mx140_wlan.hcf */ - - scnprintf(config_path, sizeof(config_path), - "%s/%s%s_%s", - base_dir, - firmware_variant, - fw_suffixes[fw_suffix_found].suffix, - filename); - } else { - /* e.g. /etc/wifi/mx140/conf/$platform_dir/wlan/wlan.hcf */ - - scnprintf(config_path, sizeof(config_path), - "%s/%s%s/%s/%s%s%s/%s", - base_dir, - firmware_variant, - fw_suffixes[fw_suffix_found].suffix, - MX140_FW_CONF_SUBDIR, - platform_dir, - (platform_dir[0] != '\0' ? "/" : ""), /* add "/" if platform_dir not empty */ - config_rel_path, - filename); - } - SCSC_TAG_INFO(MX_FILE, "try %s\n", config_path); - - r = mx140_request_file(mx, config_path, conf); - - /* Confirm what we read */ - if (r == 0) - SCSC_TAG_INFO(MX_FILE, "loaded %s\n", config_path); - - return r; -} - -int mx140_file_request_conf(struct scsc_mx *mx, - const struct firmware **conf, - const char *config_rel_path, - const char *filename) -{ - int r; - - /* First, if the config subdirectory has been overriden by cfg_platform - * module parameter, search only in that location. - */ - if (strcmp(cfg_platform, "default")) { - SCSC_TAG_INFO(MX_FILE, "module param cfg_platform = %s\n", cfg_platform); - return __mx140_file_request_conf(mx, conf, cfg_platform, config_rel_path, filename, false); - } - - /* Search in generic location. This is an override. - * e.g. /etc/wifi/mx140/conf/wlan/wlan.hcf - */ - r = __mx140_file_request_conf(mx, conf, "", config_rel_path, filename, false); - -#if defined CONFIG_SCSC_WLBT_CONFIG_PLATFORM - /* Then search in platform location - * e.g. /etc/wifi/mx140/conf/$platform_dir/wlan/wlan.hcf - */ - if (r) { - const char *plat = CONFIG_SCSC_WLBT_CONFIG_PLATFORM; - - /* Don't bother if plat is empty string */ - if (plat[0] != '\0') - r = __mx140_file_request_conf(mx, conf, plat, config_rel_path, filename, false); - } -#endif - - /* Finally request "flat" conf, where all hcf files are in FW root dir - * e.g. /etc/wifi/-wlan.hcf - */ - if (r) - r = __mx140_file_request_conf(mx, conf, "", config_rel_path, filename, true); - - return r; -} - -EXPORT_SYMBOL(mx140_file_request_conf); - -/* Reads a debug configuration file into memory (f/w profile specific) */ -int mx140_file_request_debug_conf(struct scsc_mx *mx, const struct firmware **conf, const char *config_rel_path) -{ - char config_path[MX140_FW_PATH_MAX_LENGTH]; - - if (mx140_basedir_file(mx)) - return -ENOENT; - - /* e.g. /etc/wifi/mx140/debug/log_strings.bin */ - - scnprintf(config_path, sizeof(config_path), "%s/%s%s/%s/%s", - base_dir, - firmware_variant, - fw_suffixes[fw_suffix_found].suffix, - MX140_FW_DEBUG_SUBDIR, - config_rel_path); - - return mx140_request_file(mx, config_path, conf); -} -EXPORT_SYMBOL(mx140_file_request_debug_conf); - -/* Read device configuration file into memory (whole device specific) */ -int mx140_file_request_device_conf(struct scsc_mx *mx, const struct firmware **conf, const char *config_rel_path) -{ - char config_path[MX140_FW_PATH_MAX_LENGTH]; - - if (mx140_basedir_file(mx)) - return -ENOENT; - - /* e.g. /etc/wifi/conf/wlan/mac.txt */ - - snprintf(config_path, sizeof(config_path), "%s/%s%s/%s", - base_dir, - fw_suffixes[fw_suffix_found].suffix, - MX140_FW_CONF_SUBDIR, - config_rel_path); - - return mx140_request_file(mx, config_path, conf); -} -EXPORT_SYMBOL(mx140_file_request_device_conf); - -/* Release configuration file memory. */ -void mx140_file_release_conf(struct scsc_mx *mx, const struct firmware *conf) -{ - (void)mx; - - mx140_release_file(mx, conf); -} -EXPORT_SYMBOL(mx140_file_release_conf); - -static int __mx140_file_download_fw(struct scsc_mx *mx, void *dest, size_t dest_size, u32 *fw_image_size, const char *fw_suffix) -{ - const struct firmware *firm; - int r = 0; - char img_path_name[MX140_FW_PATH_MAX_LENGTH]; - - if (mx140_basedir_file(mx)) - return -ENOENT; - - SCSC_TAG_INFO(MX_FILE, "firmware_variant=%s (%s)\n", firmware_variant, fw_suffix); - - /* e.g. /etc/wifi/mx140.bin */ - scnprintf(img_path_name, sizeof(img_path_name), "%s/%s%s.bin", - base_dir, - firmware_variant, - fw_suffix); - - SCSC_TAG_INFO(MX_FILE, "Load WLBT fw %s in shared address %p\n", img_path_name, dest); - r = mx140_request_file(mx, img_path_name, &firm); - if (r) { - SCSC_TAG_ERR(MX_FILE, "Error Loading FW, error %d\n", r); - return r; - } - SCSC_TAG_DEBUG(MX_FILE, "FW Download, size %zu\n", firm->size); - - if (firm->size > dest_size) { - SCSC_TAG_ERR(MX_FILE, "firmware image too big for buffer (%zu > %u)", dest_size, *fw_image_size); - r = -EINVAL; - } else { - memcpy(dest, firm->data, firm->size); - *fw_image_size = firm->size; - } - mx140_release_file(mx, firm); - return r; -} - -/* Download firmware binary into a buffer supplied by the caller */ -int mx140_file_download_fw(struct scsc_mx *mx, void *dest, size_t dest_size, u32 *fw_image_size) -{ - int r; - int i; - int manual; - - /* Override to use the verbatim image only */ - manual = !strcmp(firmware_hw_ver, "manual"); - if (manual) { - SCSC_TAG_INFO(MX_FILE, "manual hw version\n"); - fw_suffix_found = sizeof(fw_suffixes) / sizeof(fw_suffixes[0]) - 1; - } - - SCSC_TAG_DEBUG(MX_FILE, "fw_suffix_found %d\n", fw_suffix_found); - - /* If we know which f/w suffix to use, select it immediately */ - if (fw_suffix_found != -1) { - r = __mx140_file_download_fw(mx, dest, dest_size, fw_image_size, fw_suffixes[fw_suffix_found].suffix); - goto done; - } - - /* Otherwise try the list */ - for (i = 0; i < sizeof(fw_suffixes) / sizeof(fw_suffixes[0]); i++) { - /* Try to find each suffix in turn */ - SCSC_TAG_INFO(MX_FILE, "try %d %s\n", i, fw_suffixes[i].suffix); - r = __mx140_file_download_fw(mx, dest, dest_size, fw_image_size, fw_suffixes[i].suffix); - if (r != -ENOENT) - break; - } - - /* Save this for next time */ - if (r == 0) - fw_suffix_found = i; -done: - /* Update firmware_hw_ver to reflect what got auto selected, for moredump */ - if (fw_suffix_found != -1 && !manual) { - /* User will only read this, so casting away const is safe */ - firmware_hw_ver = (char *)fw_suffixes[fw_suffix_found].suffix; - } - return r; -} - -int mx140_request_file(struct scsc_mx *mx, char *path, const struct firmware **firmp) -{ - struct file *f; - mm_segment_t fs; - struct kstat stat; - const int max_read_size = 4096; - int r, whats_left, to_read, size; - struct firmware *firm; - char *buf, *p; - - SCSC_TAG_DEBUG(MX_FILE, "request %s\n", path); - - *firmp = NULL; - - /* Check FS is ready */ - - /* Try to determine base dir */ - r = mx140_basedir_file(mx); - if (r) { - SCSC_TAG_ERR(MX_FILE, "detect failed for fw base_dir %d\n", r); - return r; - } - - /* Current segment. */ - fs = get_fs(); - /* Set to kernel segment. */ - set_fs(get_ds()); - - r = vfs_stat(base_dir, &stat); - if (r != 0) { - set_fs(fs); - SCSC_TAG_ERR(MX_FILE, "vfs_stat() failed for %s\n", base_dir); - return -EAGAIN; - } - - /* Check f/w bin */ - r = vfs_stat(path, &stat); - if (r != 0) { - set_fs(fs); - SCSC_TAG_ERR(MX_FILE, "vfs_stat() failed for %s\n", path); - return -ENOENT; - } - /* Revert to original segment. */ - set_fs(fs); - - /* Round up for minimum sizes */ - size = (stat.size + 256) & ~255; - /* Get memory for file contents. */ - buf = vzalloc(size); - if (!buf) { - SCSC_TAG_ERR(MX_FILE, "kzalloc(%d) failed for %s\n", size, path); - return -ENOMEM; - } - p = buf; - /* Get firmware structure. */ - firm = kzalloc(sizeof(*firm), GFP_KERNEL); - if (!firm) { - vfree(buf); - SCSC_TAG_ERR(MX_FILE, "kzalloc(%zu) failed for %s\n", sizeof(*firmp), path); - return -ENOMEM; - } - /* Open the file for reading. */ - f = filp_open(path, O_RDONLY, 0); - if (IS_ERR(f)) { - vfree(buf); - kfree(firm); - SCSC_TAG_ERR(MX_FILE, "filp_open() failed for %s with %ld\n", path, PTR_ERR(f)); - return -ENOENT; - } - - whats_left = stat.size; - - fs = get_fs(); - set_fs(get_ds()); - - /* Special case if file length is reported as zero - try to read until it fails. - * This allows us to read /proc - */ - if (whats_left == 0) { - do { - r = vfs_read(f, p, max_read_size, &f->f_pos); - if (r < 0) { - SCSC_TAG_INFO(MX_FILE, "No more data %s\n", path); - break; - } - p += r; - if (r < max_read_size) { - SCSC_TAG_INFO(MX_FILE, "Read %zd from %s\n", (ptrdiff_t)(p - buf), path); - break; - } - } while (r > 0); - - goto done; - } - - /* Read at most max_read_size in each read. Loop until the whole file has - * been copied to the local buffer. - */ - while (whats_left) { - to_read = whats_left < max_read_size ? whats_left : max_read_size; - r = vfs_read(f, p, to_read, &f->f_pos); - if (r < 0) { - SCSC_TAG_ERR(MX_FILE, "error reading %s\n", path); - break; - } - if (r == 0 || r < to_read) - break; - whats_left -= r; - p += r; - } -done: - set_fs(fs); - filp_close(f, NULL); - - if (r >= 0) { - r = 0; - /* Pass to caller. Caller will free allocated memory through - * mx140_release_file(). - */ - firm->size = p - buf; - firm->data = buf; - *firmp = firm; - } else { - vfree(buf); - kfree(firm); - } - return r; - -} -EXPORT_SYMBOL(mx140_request_file); - -int mx140_release_file(struct scsc_mx *mx, const struct firmware *firmp) -{ - if (!firmp || !firmp->data) { - SCSC_TAG_ERR(MX_FILE, "firmp=%p\n", firmp); - return -EINVAL; - } - - SCSC_TAG_DEBUG(MX_FILE, "release firmp=%p, data=%p\n", firmp, firmp->data); - - vfree(firmp->data); - kfree(firmp); - return 0; -} -EXPORT_SYMBOL(mx140_release_file); - -/* Work out correct path for vendor binaries */ -int mx140_exe_path(struct scsc_mx *mx, char *path, size_t len, const char *bin) -{ - (void)mx; - - /* Set up when we detect FW path, or statically when - * auto-detect is off - */ - if (exe_dir[0] == '\0') - return -ENOENT; - - if (path == NULL) - return -EINVAL; - - snprintf(path, len, "%s/%s", exe_dir, bin); - - SCSC_TAG_DEBUG(MX_FILE, "exe: %s\n", path); - return 0; -} -EXPORT_SYMBOL(mx140_exe_path); - -/* Try to auto detect f/w directory */ -int mx140_basedir_file(struct scsc_mx *mx) -{ - struct kstat stat; - mm_segment_t fs; - int r = 0; - - /* Already worked out base dir. This is - * static if auto-detect is off. - */ - if (base_dir[0] != '\0') - return 0; - - /* Default to pre-O bin dir, until we detect O */ - strlcpy(exe_dir, MX140_EXE_DIR_SYSTEM, sizeof(exe_dir)); - - /* Current segment. */ - fs = get_fs(); - /* Set to kernel segment. */ - set_fs(get_ds()); - - /* If /system isn't present, assume platform isn't ready yet */ - r = vfs_stat("/system", &stat); - if (r != 0) { - SCSC_TAG_ERR(MX_FILE, "/system not mounted yet\n"); - r = -EAGAIN; - goto done; - } - - /* If /vendor isn't present, assume platform isn't ready yet. - * Android M and N still have /vendor, though we don't use it. - */ - r = vfs_stat("/vendor", &stat); - if (r != 0) { - SCSC_TAG_ERR(MX_FILE, "/vendor not mounted yet\n"); - r = -EAGAIN; - goto done; - } - - /* Now partitions are mounted, so let's see what's in them. */ - - /* Try /vendor partition (Oreo) first. - * If it's present, it'll contain our FW - */ - r = vfs_stat(MX140_FW_BASE_DIR_VENDOR_ETC_WIFI"/"MX140_FW_DETECT, &stat); - if (r != 0) { - SCSC_TAG_ERR(MX_FILE, "Base dir: %s/%s doesn't exist\n", - MX140_FW_BASE_DIR_VENDOR_ETC_WIFI, MX140_FW_DETECT); - base_dir[0] = '\0'; - r = -ENOENT; - } else { - strlcpy(base_dir, MX140_FW_BASE_DIR_VENDOR_ETC_WIFI, sizeof(base_dir)); - fw_base_dir = MX140_FW_BASE_DIR_VENDOR_ETC_WIFI; - strlcpy(exe_dir, MX140_EXE_DIR_VENDOR, sizeof(exe_dir)); - goto done; - } - - /* Try /system partition (pre-Oreo) */ - r = vfs_stat(MX140_FW_BASE_DIR_SYSTEM_ETC_WIFI"/"MX140_FW_DETECT, &stat); - if (r != 0) { - SCSC_TAG_ERR(MX_FILE, "Base dir: %s/%s doesn't exist\n", - MX140_FW_BASE_DIR_SYSTEM_ETC_WIFI, MX140_FW_DETECT); - base_dir[0] = '\0'; - r = -ENOENT; - } else { - strlcpy(base_dir, MX140_FW_BASE_DIR_SYSTEM_ETC_WIFI, sizeof(base_dir)); - fw_base_dir = MX140_FW_BASE_DIR_SYSTEM_ETC_WIFI; - } - -done: - /* Restore segment */ - set_fs(fs); - SCSC_TAG_INFO(MX_FILE, "WLBT fw base dir is %s\n", base_dir[0] ? base_dir : "not found"); - - return r; -} - -/* Select file for h/w version from filesystem */ -int mx140_file_select_fw(struct scsc_mx *mx, u32 hw_ver) -{ - int i; - - SCSC_TAG_INFO(MX_FILE, "select f/w for 0x%04x\n", hw_ver); - -#ifdef SCSC_MULTI_RF_CHIP_ID - hw_ver = (hw_ver & 0x00ff); /* LSB is the RF HW ID (e.g. S610) */ -#else - hw_ver = (hw_ver & 0xff00) >> 8; /* MSB is the RF HW rev (e.g. EVT1.1) */ -#endif - - for (i = 0; i < sizeof(fw_suffixes) / sizeof(fw_suffixes[0]); i++) { - if (fw_suffixes[i].hw_ver == hw_ver) { - fw_suffix_found = i; - SCSC_TAG_DEBUG(MX_FILE, "f/w for 0x%04x: index %d, suffix '%s'\n", - hw_ver, i, fw_suffixes[i].suffix); - return 0; - } - } - - SCSC_TAG_ERR(MX_FILE, "No known f/w for 0x%04x, default to catchall\n", hw_ver); - - /* Enable when a unified FW image is installed */ -#ifdef MX140_UNIFIED_HW_FW - /* The last f/w is the non-suffixed ".bin", assume it's compatible */ - fw_suffix_found = i - 1; -#else - fw_suffix_found = -1; /* None found */ -#endif - return -EINVAL; -} - -/* Query whether this HW is supported by the current FW file set */ -bool mx140_file_supported_hw(struct scsc_mx *mx, u32 hw_ver) -{ -#ifdef SCSC_MULTI_RF_CHIP_ID - hw_ver = (hw_ver & 0x00ff); /* LSB is the RF HW ID (e.g. S610) */ -#else - hw_ver = (hw_ver & 0xff00) >> 8; /* MSB is the RF HW rev (e.g. EVT1.0) */ -#endif - /* Assume installed 0xff is always compatible, and f/w will panic if it isn't */ - if (fw_suffixes[fw_suffix_found].hw_ver == 0xff) - return true; - - /* Does the select f/w match the hw_ver from chip? */ - return (fw_suffixes[fw_suffix_found].hw_ver == hw_ver); -} diff --git a/drivers/misc/samsung/scsc/mx250_fm.c b/drivers/misc/samsung/scsc/mx250_fm.c deleted file mode 100755 index 5aa8632503b2..000000000000 --- a/drivers/misc/samsung/scsc/mx250_fm.c +++ /dev/null @@ -1,396 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mxman.h" /* Special case service driver that looks inside mxman */ - -#ifdef CONFIG_SCSC_FM_TEST -#include "mx250_fm_test.h" -#endif - - -struct scsc_mx_fm_client { - /* scsc_service_client has to be the first */ - struct scsc_service_client fm_service_client; - struct scsc_service *fm_service; - struct scsc_mx *mx; - bool fm_api_available; - scsc_mifram_ref ref; - struct workqueue_struct *fm_client_wq; - struct work_struct fm_client_work; - struct completion fm_client_work_completion; - int fm_client_work_completion_status; - bool ldo_on; -}; - -static struct scsc_mx_fm_client *fm_client; -/* service to start */ -static int service_id = SCSC_SERVICE_ID_FM; - -static DEFINE_MUTEX(ss_lock); - -static u8 fm_client_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void)client; - SCSC_TAG_DEBUG(FM, "OK\n"); - return err->level; -} - - -static bool fm_client_stop_on_failure(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void)client; - (void)err; - mutex_lock(&ss_lock); - fm_client->fm_api_available = false; - mutex_unlock(&ss_lock); - SCSC_TAG_DEBUG(FM, "OK\n"); - return false; -} - -static void fm_client_failure_reset(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code) -{ - (void)client; - (void)level; - (void)scsc_syserr_code; - SCSC_TAG_DEBUG(FM, "OK\n"); -} - -static int stop_close_service(void) -{ - int r; - - if (!fm_client->fm_service) { - SCSC_TAG_ERR(FM, "No fm_service\n"); - r = -EINVAL; - goto done; - } - - r = scsc_mx_service_stop(fm_client->fm_service); - if (r) { - SCSC_TAG_ERR(FM, "scsc_mx_service_stop(fm_service) failed %d\n", r); - goto done; - } - SCSC_TAG_DEBUG(FM, "scsc_mx_service_stop(fm_service) OK\n"); - - scsc_mx_service_mifram_free(fm_client->fm_service, fm_client->ref); - - r = scsc_mx_service_close(fm_client->fm_service); - if (r) { - SCSC_TAG_ERR(FM, "scsc_mx_service_close(fm_service) failed %d\n", r); - goto done; - } else - SCSC_TAG_DEBUG(FM, "scsc_mx_service_close(fm_service) OK\n"); - - fm_client->fm_service = NULL; - fm_client->ref = 0; -done: - return r; -} - -static int open_start_service(void) -{ - struct scsc_service *fm_service; - int r; - int r2; - struct fm_ldo_conf *ldo_conf; - scsc_mifram_ref ref; - - fm_service = scsc_mx_service_open(fm_client->mx, service_id, &fm_client->fm_service_client, &r); - if (!fm_service) { - r = -EINVAL; - SCSC_TAG_ERR(FM, "scsc_mx_service_open(fm_service) failed %d\n", r); - goto done; - } - /* Allocate memory */ - r = scsc_mx_service_mifram_alloc(fm_service, sizeof(struct fm_ldo_conf), &ref, 32); - if (r) { - SCSC_TAG_ERR(FM, "scsc_mx_service_mifram_alloc(fm_service) failed %d\n", r); - r2 = scsc_mx_service_close(fm_service); - if (r2) - SCSC_TAG_ERR(FM, "scsc_mx_service_close(fm_service) failed %d\n", r2); - goto done; - } - ldo_conf = (struct fm_ldo_conf *)scsc_mx_service_mif_addr_to_ptr(fm_service, ref); - ldo_conf->version = FM_LDO_CONFIG_VERSION; - ldo_conf->ldo_on = fm_client->ldo_on; - - r = scsc_mx_service_start(fm_service, ref); - if (r) { - SCSC_TAG_ERR(FM, "scsc_mx_service_start(fm_service) failed %d\n", r); - r2 = scsc_mx_service_close(fm_service); - if (r2) - SCSC_TAG_ERR(FM, "scsc_mx_service_close(fm_service) failed %d\n", r2); - scsc_mx_service_mifram_free(fm_service, ref); - goto done; - } - - fm_client->fm_service = fm_service; - fm_client->ref = ref; -done: - return r; -} - -static int open_start_close_service(void) -{ - int r; - - r = open_start_service(); - if (r) { - SCSC_TAG_ERR(FM, "Error starting service: open_start_service(fm_service) failed %d\n", r); - - if (!fm_client->ldo_on) { - /* Do not return here. For the case where WLBT FW is crashed, and FM off request is - * rejected, it's safest to continue to let scsc_service_on_halt_ldos_off() reset - * the global flag to indicate that FM is no longer needed when WLBT next boots. - * Otherwise LDO could be stuck always-on. - */ - } else - return r; - } - - if (fm_client->ldo_on) { - /* FM turning on */ - mxman_fm_on_halt_ldos_on(); - - } else { - /* FM turning off */ - mxman_fm_on_halt_ldos_off(); - - /* Invalidate stored FM params */ - mxman_fm_set_params(NULL); - } - - r = stop_close_service(); - if (r) { - SCSC_TAG_ERR(FM, "Error starting service: stop_close_service(fm_service) failed %d\n", r); - return r; - } - return 0; -} - -static void fm_client_work_func(struct work_struct *work) -{ - SCSC_TAG_DEBUG(FM, "mx250: %s\n", __func__); - - fm_client->fm_client_work_completion_status = open_start_close_service(); - if (fm_client->fm_client_work_completion_status) { - SCSC_TAG_ERR(FM, "open_start_close_service(fm_service) failed %d\n", - fm_client->fm_client_work_completion_status); - } else { - SCSC_TAG_DEBUG(FM, "OK\n"); - } - complete(&fm_client->fm_client_work_completion); - -} - -static void fm_client_wq_init(void) -{ - fm_client->fm_client_wq = create_singlethread_workqueue("fm_client_wq"); - INIT_WORK(&fm_client->fm_client_work, fm_client_work_func); -} - -static void fm_client_wq_stop(void) -{ - cancel_work_sync(&fm_client->fm_client_work); - flush_workqueue(fm_client->fm_client_wq); -} - -static void fm_client_wq_deinit(void) -{ - fm_client_wq_stop(); - destroy_workqueue(fm_client->fm_client_wq); -} - -static void fm_client_wq_start(void) -{ - queue_work(fm_client->fm_client_wq, &fm_client->fm_client_work); -} - -static int fm_client_wq_start_blocking(void) -{ - SCSC_TAG_DEBUG(FM, "mx250: %s\n", __func__); - - fm_client_wq_start(); - wait_for_completion(&fm_client->fm_client_work_completion); - if (fm_client->fm_client_work_completion_status) { - SCSC_TAG_ERR(FM, "%s failed: fm_client_wq_completion_status = %d\n", - __func__, fm_client->fm_client_work_completion_status); - return fm_client->fm_client_work_completion_status; - } - SCSC_TAG_DEBUG(FM, "OK\n"); - return 0; -} - -static int mx250_fm_re(bool ldo_on) -{ - int r; - - mutex_lock(&ss_lock); - SCSC_TAG_DEBUG(FM, "mx250: %s\n", __func__); - if (!fm_client) { - SCSC_TAG_ERR(FM, "fm_client = NULL\n"); - mutex_unlock(&ss_lock); - return -ENODEV; - } - - if (!fm_client->fm_api_available) { - SCSC_TAG_WARNING(FM, "FM LDO API unavailable\n"); - mutex_unlock(&ss_lock); - return -EAGAIN; - } - fm_client->ldo_on = ldo_on; - reinit_completion(&fm_client->fm_client_work_completion); - r = fm_client_wq_start_blocking(); - mutex_unlock(&ss_lock); - return r; - -} - -/* - * FM Radio is starting, tell WLBT drivers - */ -int mx250_fm_request(void) -{ - - SCSC_TAG_INFO(FM, "request\n"); - return mx250_fm_re(true); -} -EXPORT_SYMBOL(mx250_fm_request); - -/* - * FM Radio is stopping, tell WLBT drivers - */ -int mx250_fm_release(void) -{ - SCSC_TAG_INFO(FM, "release\n"); - return mx250_fm_re(false); -} -EXPORT_SYMBOL(mx250_fm_release); - -/* - * FM Radio parameters are changing, tell WLBT drivers - */ -void mx250_fm_set_params(struct wlbt_fm_params *info) -{ - SCSC_TAG_DEBUG(FM, "mx250: %s\n", __func__); - - if (!info) - return; - - mutex_lock(&ss_lock); - - SCSC_TAG_INFO(FM, "freq %u\n", info->freq); - - mxman_fm_set_params(info); - - mutex_unlock(&ss_lock); -} -EXPORT_SYMBOL(mx250_fm_set_params); - -void fm_client_module_probe(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, - enum scsc_module_client_reason reason) -{ - /* Avoid unused error */ - (void)module_client; - - SCSC_TAG_INFO(FM, "probe\n"); - - mutex_lock(&ss_lock); - if (reason == SCSC_MODULE_CLIENT_REASON_HW_PROBE) { - fm_client = kzalloc(sizeof(*fm_client), GFP_KERNEL); - if (!fm_client) { - mutex_unlock(&ss_lock); - return; - } - init_completion(&fm_client->fm_client_work_completion); - fm_client_wq_init(); - fm_client->fm_service_client.failure_notification = fm_client_failure_notification; - fm_client->fm_service_client.stop_on_failure_v2 = fm_client_stop_on_failure; - fm_client->fm_service_client.failure_reset_v2 = fm_client_failure_reset; - fm_client->mx = mx; - } - fm_client->fm_api_available = true; - SCSC_TAG_DEBUG(FM, "OK\n"); - mutex_unlock(&ss_lock); -} - -void fm_client_module_remove(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, - enum scsc_module_client_reason reason) -{ - /* Avoid unused error */ - (void)module_client; - - SCSC_TAG_INFO(FM, "remove\n"); - - mutex_lock(&ss_lock); - if (reason == SCSC_MODULE_CLIENT_REASON_HW_REMOVE) { - if (!fm_client) { - mutex_unlock(&ss_lock); - return; - } - if (fm_client->mx != mx) { - SCSC_TAG_ERR(FM, "fm_client->mx != mx\n"); - mutex_unlock(&ss_lock); - return; - } - fm_client_wq_deinit(); - kfree(fm_client); - fm_client = NULL; - } - SCSC_TAG_DEBUG(FM, "OK\n"); - mutex_unlock(&ss_lock); -} - -/* FM client driver registration */ -struct scsc_mx_module_client fm_client_driver = { - .name = "FM client driver", - .probe = fm_client_module_probe, - .remove = fm_client_module_remove, -}; - -static int __init scsc_fm_client_module_init(void) -{ - int r; - - SCSC_TAG_INFO(FM, "init\n"); - - r = scsc_mx_module_register_client_module(&fm_client_driver); - if (r) { - SCSC_TAG_ERR(FM, "scsc_mx_module_register_client_module failed: r=%d\n", r); - return r; - } -#ifdef CONFIG_SCSC_FM_TEST - mx250_fm_test_init(); -#endif - return 0; -} - -static void __exit scsc_fm_client_module_exit(void) -{ - SCSC_TAG_INFO(FM, "exit\n"); - scsc_mx_module_unregister_client_module(&fm_client_driver); -#ifdef CONFIG_SCSC_FM_TEST - mx250_fm_test_exit(); -#endif - SCSC_TAG_DEBUG(FM, "exit\n"); -} - -late_initcall(scsc_fm_client_module_init); -module_exit(scsc_fm_client_module_exit); - -MODULE_DESCRIPTION("FM Client Driver"); -MODULE_AUTHOR("SCSC"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/samsung/scsc/mx250_fm_test.c b/drivers/misc/samsung/scsc/mx250_fm_test.c deleted file mode 100644 index 7132367ef303..000000000000 --- a/drivers/misc/samsung/scsc/mx250_fm_test.c +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include "scsc_mx_impl.h" - -/* char device entry declarations */ -static dev_t mx250_fm_test_dev_t; -static struct class *mx250_fm_test_class; -static struct cdev *mx250_fm_test_cdev; - - -static int mx250_fm_test_dev_open(struct inode *inode, struct file *file) -{ - return 0; -} - -static int mx250_fm_test_dev_release(struct inode *inode, struct file *file) -{ - return 0; -} - - -static ssize_t mx250_fm_test_dev_write(struct file *file, const char *data, size_t len, loff_t *offset) -{ - unsigned long count; - char str[20]; /* One value and carry return */ - long val = 0; - struct wlbt_fm_params params; - int r; - - count = copy_from_user(str, data, len); - - str[sizeof(str) - 1] = 0; - if (len < sizeof(str)) - str[len - 1] = 0; - - r = kstrtol(str, 0, &val); - if (r) { - SCSC_TAG_ERR(FM_TEST, "parse error %d, l=%zd\n", r, len); - goto error; - } - - if (val == 1) - mx250_fm_request(); - else if (val == 0) - mx250_fm_release(); - else { - /* All other values are frequency info */ - params.freq = (u32)val; - - SCSC_TAG_INFO(FM_TEST, "FM freq=%u\n", params.freq); - - mx250_fm_set_params(¶ms); - } -error: - return len; -} - -static ssize_t mx250_fm_test_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) -{ - return length; -} - -static const struct file_operations mx250_fm_test_dev_fops = { - .owner = THIS_MODULE, - .open = mx250_fm_test_dev_open, - .read = mx250_fm_test_dev_read, - .write = mx250_fm_test_dev_write, - .release = mx250_fm_test_dev_release, -}; - -/* FM service driver registration */ -void mx250_fm_test_init(void) -{ - int ret; - - SCSC_TAG_INFO(FM_TEST, "Registering mx250 TEST\n"); - - ret = alloc_chrdev_region(&mx250_fm_test_dev_t, 0, 1, "mx250_fm_test-cdev"); - if (ret < 0) { - SCSC_TAG_ERR(FM_TEST, "failed to alloc chrdev region\n"); - goto fail_alloc_chrdev_region; - } - - mx250_fm_test_cdev = cdev_alloc(); - if (!mx250_fm_test_cdev) { - ret = -ENOMEM; - SCSC_TAG_ERR(FM_TEST, "failed to alloc cdev\n"); - goto fail_alloc_cdev; - } - - cdev_init(mx250_fm_test_cdev, &mx250_fm_test_dev_fops); - ret = cdev_add(mx250_fm_test_cdev, mx250_fm_test_dev_t, 1); - if (ret < 0) { - SCSC_TAG_ERR(FM_TEST, "failed to add cdev\n"); - goto fail_add_cdev; - } - - mx250_fm_test_class = class_create(THIS_MODULE, "mx250_fm_test"); - if (!mx250_fm_test_class) { - ret = -EEXIST; - SCSC_TAG_ERR(FM_TEST, "failed to create class\n"); - goto fail_create_class; - } - - if (!device_create(mx250_fm_test_class, NULL, mx250_fm_test_dev_t, NULL, "mx250_fm_test_%d", - MINOR(mx250_fm_test_dev_t))) { - ret = -EINVAL; - SCSC_TAG_ERR(FM_TEST, "failed to create device\n"); - goto fail_create_device; - } - - return; -fail_create_device: - class_destroy(mx250_fm_test_class); -fail_create_class: - cdev_del(mx250_fm_test_cdev); -fail_add_cdev: -fail_alloc_cdev: - unregister_chrdev_region(mx250_fm_test_dev_t, 1); -fail_alloc_chrdev_region: - return; -} - -void mx250_fm_test_exit(void) -{ - device_destroy(mx250_fm_test_class, mx250_fm_test_dev_t); - class_destroy(mx250_fm_test_class); - cdev_del(mx250_fm_test_cdev); - unregister_chrdev_region(mx250_fm_test_dev_t, 1); -} diff --git a/drivers/misc/samsung/scsc/mx250_fm_test.h b/drivers/misc/samsung/scsc/mx250_fm_test.h deleted file mode 100644 index 6b92a15498c5..000000000000 --- a/drivers/misc/samsung/scsc/mx250_fm_test.h +++ /dev/null @@ -1,13 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MX250_FM_TEST_H___ -#define __MX250_FM_TEST_H___ - - -void mx250_fm_test_init(void); -void mx250_fm_test_exit(void); -#endif /* __MX250_FM_TEST_H___*/ diff --git a/drivers/misc/samsung/scsc/mx_dbg_sampler.c b/drivers/misc/samsung/scsc/mx_dbg_sampler.c deleted file mode 100755 index 5d2cf4a25754..000000000000 --- a/drivers/misc/samsung/scsc/mx_dbg_sampler.c +++ /dev/null @@ -1,783 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mx_dbg_sampler.h" -#include "scsc_mif_abs.h" -#include "mxman.h" -#include "scsc_mx_impl.h" -#include "miframman.h" - -#include - -static unsigned int source_addr = 0xd0300028; -module_param(source_addr, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(source_addr, "Relative address of Location to sample (usually a register) - default: 0xd0300028. Loaded at /dev open"); - -static unsigned int num_bytes = 4; -module_param(num_bytes, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(num_bytes, "Number of significant octets (1,2 or 4) to log (lsbytes from source) - default: 4. Loaded at /dev open"); - -static unsigned int period_usecs; -module_param(period_usecs, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(period_usecs, "Sampling period. 0 means as fast as possible (powers of 2 only) - default: 0. Loaded at /dev open"); - -static bool auto_start; -module_param(auto_start, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(auto_start, "Start/stop sampling when service is started/stopped? - default: N. Loaded at /dev open"); - -static unsigned int buf_len = 512 * 1024; -module_param(buf_len, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(buf_len, "Circular buffer length (octets, 2^n) in bytes - default: 524288. Loaded at /dev open"); - -static unsigned int kfifo_len = 4 * 1024 * 1024; -module_param(kfifo_len, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(kfifo_len, "Kfifo buffer length (octets, 2^n) in bytes - default: 4194304. Loaded at /dev open"); - -static bool self_test; -module_param(self_test, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(self_test, "Execute self test by triggering a Kernel thread which writes into shared memory and then calls irg handler - default: N. Loaded at /dev open"); - -#define DRV_NAME "mx_dbg_sampler" -#define DEVICE_NAME "mx_dbg_sampler" - -#ifndef VM_RESERVED -#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) -#endif - -#define VER_MAJOR 0 -#define VER_MINOR 0 - -#define SCSC_MX_DEBUG_NODE 1 - -#define SCSC_MX_DEBUG_INTERFACES (5 * (SCSC_MX_DEBUG_NODE)) - -DECLARE_BITMAP(bitmap_dbg_sampler_minor, SCSC_MX_DEBUG_INTERFACES); - -#define NO_ERROR 0 -#define BUFFER_OVERFLOW 1 -#define KFIFO_ERROR 2 -#define KFIFO_FULL 3 - -struct mx_dbg_sampler_dev { - /* file pointer */ - struct file *filp; - /* char device */ - struct cdev cdev; - /*device pointer*/ - struct device *dev; - /* mx_wlan_client */ - struct scsc_service_client mx_client; - /*service pointer*/ - struct scsc_service *service; - /*service pointer*/ - scsc_mifram_ref ref; - /*mx pointer*/ - struct scsc_mx *mx; - /* Associated kfifo */ - DECLARE_KFIFO_PTR(fifo, u8); - /* Associated read_wait queue.*/ - wait_queue_head_t read_wait; - /* Associated debug_buffer */ - struct debug_sampler_config info; - /* Buffer read index */ - u32 read_idx; - /* Device in error */ - u8 error; - /* Device node spinlock for IRQ */ - spinlock_t spinlock; - /* Device node mutex for fops */ - struct mutex mutex; - /* To profile kfifo num elements */ - u32 kfifo_max; - /* Device is in use */ - bool in_use; -}; - -/** - * SCSC User Space debug sampler interface (singleton) - */ -static struct { - dev_t device; - struct class *class_mx_dbg_sampler; - struct mx_dbg_sampler_dev devs[SCSC_MX_DEBUG_INTERFACES]; -} mx_dbg_sampler; - -static int recovery_in_progress; - -static u8 mx_dbg_sampler_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void)client; - SCSC_TAG_INFO(MX_SAMPLER, "OK\n"); - return err->level; -} - - -static bool mx_dbg_sampler_stop_on_failure(struct scsc_service_client *client, struct mx_syserr_decode *err) -{ - (void)client; - (void)err; - SCSC_TAG_INFO(MX_SAMPLER, "TODO\n"); - recovery_in_progress = 1; - return false; -} - -static void mx_dbg_sampler_failure_reset(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code) -{ - (void)client; - (void)level; - (void)scsc_syserr_code; - SCSC_TAG_INFO(MX_SAMPLER, "TODO\n"); -} - -static void mx_wlan_read_process(const void *data, size_t length, struct mx_dbg_sampler_dev *mx_dev) -{ - int ret; - void *read_ptr; - u32 elements; - - /* Adjust lenght for kfifo type (u8)- elements -*/ - elements = length; - - if (mx_dev->filp) { - /* put string into the fifo */ - if (kfifo_avail(&mx_dev->fifo) >= elements) { - /* Push values in Fifo*/ - read_ptr = (void *)data + (mx_dev->read_idx & (buf_len - 1)); - ret = kfifo_in(&mx_dev->fifo, read_ptr, elements); - mx_dev->read_idx += ret; - if (ret != elements || ret == 0) { - mx_dev->error = KFIFO_ERROR; - return; - } - ret = kfifo_len(&mx_dev->fifo); - if (ret > mx_dev->kfifo_max) - mx_dev->kfifo_max = ret; - } else { - /* Mask interrupt to avoid interrupt storm */ - mx_dev->error = KFIFO_FULL; - return; - } - wake_up_interruptible(&mx_dev->read_wait); - } - /* Device is closed. Silenty return */ -} - -static void mx_dbg_sampler_irq_handler(int irq, void *data) -{ - struct mx_dbg_sampler_dev *mx_dev = (struct mx_dbg_sampler_dev *)data; - struct scsc_service *service = mx_dev->service; - u32 write_ref; - u32 data_ref; - void *write_ptr; - void *data_ptr; - u32 read_idx; - u32 write_idx; - size_t to_read; - unsigned long flags; - - spin_lock_irqsave(&mx_dev->spinlock, flags); - - /* check whether service has been released */ - if (!mx_dev->service) { - spin_unlock_irqrestore(&mx_dev->spinlock, flags); - return; - } - - read_idx = mx_dev->read_idx; - - write_ref = mx_dev->info.buffer_info.write_index_offset; - write_ptr = scsc_mx_service_mif_addr_to_ptr(service, write_ref); - write_idx = *((u32 *)write_ptr); - - to_read = abs((s32)write_idx - (s32)read_idx); - - /* TODO: Decide whether we need to do the memdump on a workqueue/tasklet or just in the int handler */ - if (to_read > mx_dev->info.buffer_info.buf_len) { - scsc_service_mifintrbit_bit_clear(service, irq); - scsc_service_mifintrbit_bit_mask(service, irq); - mx_dev->error = BUFFER_OVERFLOW; - goto end; - } - - data_ref = mx_dev->info.buffer_info.buf_offset; - data_ptr = scsc_mx_service_mif_addr_to_ptr(service, data_ref); - mx_wlan_read_process(data_ptr, to_read, mx_dev); /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(service, irq); - scsc_service_mifintrbit_bit_unmask(service, irq); -end: - spin_unlock_irqrestore(&mx_dev->spinlock, flags); - - /* Mask if dev is in error */ - /* We shouldn't be printing out lots of stuff here, but it is in error condition */ - if (mx_dev->error != NO_ERROR) { - scsc_service_mifintrbit_bit_mask(service, irq); - if (mx_dev->error == BUFFER_OVERFLOW) - SCSC_TAG_ERR(MX_SAMPLER, "Error, Buffer Overflow %zu write_idx 0x%x read_idex 0x%x\n", to_read, write_idx, read_idx); - else if (mx_dev->error == KFIFO_ERROR) - SCSC_TAG_ERR(MX_SAMPLER, "Error Pushing values in kfifo\n"); - else if (mx_dev->error == KFIFO_FULL) - SCSC_TAG_ERR(MX_SAMPLER, "Error kfifo is full\n"); - } -} - -static struct task_struct *mx_dbg_sampler_task; - -#define BULK_DATA (16 * 1024) -int mx_dbg_sampler_thread(void *data) -{ - struct mx_dbg_sampler_dev *dev = (struct mx_dbg_sampler_dev *)data; - struct scsc_service *service = dev->service; - u32 write; - u32 mem; - void *write_ptr; - u32 *mem_ptr; - u32 val; - u32 i; - u32 end; - - while (!kthread_should_stop() && !(dev->error != NO_ERROR)) { - write = dev->info.buffer_info.write_index_offset; - write_ptr = scsc_mx_service_mif_addr_to_ptr(service, write); - val = *((u32 *)write_ptr); - val += BULK_DATA; - *((u32 *)write_ptr) = val; - - end = BULK_DATA; - - - mem = dev->info.buffer_info.buf_offset; - mem_ptr = scsc_mx_service_mif_addr_to_ptr(service, mem); - - mem_ptr += dev->read_idx / sizeof(u32); - - for (i = 0; i < end / 4; i++) - *((u32 *)mem_ptr++) = 0x33323130; - - mx_dbg_sampler_irq_handler(0, dev); - mdelay(100); - } - mx_dbg_sampler_task = NULL; - return 0; -} - -static int mx_dbg_sampler_allocate_resources(struct scsc_service *service, struct mx_dbg_sampler_dev *mx_dev) -{ - scsc_mifram_ref ref, ref_buffer, ref_index; - int ret = 0; - struct debug_sampler_align *mem; - - /* Allocate memory */ - ret = scsc_mx_service_mifram_alloc(service, buf_len + sizeof(struct debug_sampler_align), &ref, 64); - if (ret) - return -ENOMEM; - mem = (struct debug_sampler_align *)scsc_mx_service_mif_addr_to_ptr(service, ref); - - /* Allocate interrupt */ - ret = scsc_service_mifintrbit_register_tohost(service, mx_dbg_sampler_irq_handler, mx_dev); - if (ret < 0) { - SCSC_TAG_ERR(MX_SAMPLER, "Error allocating interrupt\n"); - scsc_mx_service_mifram_free(service, ref); - return ret; - } - /* Populate the buffer_info */ - mem->config.version = mx_dev->info.version = 0; - - scsc_mx_service_mif_ptr_to_addr(service, &mem->mem, &ref_buffer); - mem->config.buffer_info.buf_offset = mx_dev->info.buffer_info.buf_offset = ref_buffer; - - mem->config.buffer_info.buf_len = mx_dev->info.buffer_info.buf_len = buf_len; - - scsc_mx_service_mif_ptr_to_addr(service, &mem->index, &ref_index); - mem->config.buffer_info.write_index_offset = - mx_dev->info.buffer_info.write_index_offset = ref_index; - - /* Reset write index */ - mem->index = 0; - - mem->config.buffer_info.intr_num = mx_dev->info.buffer_info.intr_num = ret; - - mem->config.sample_spec.source_addr = source_addr; - mem->config.sample_spec.num_bytes = num_bytes; - mem->config.sample_spec.period_usecs = period_usecs; - mem->config.auto_start = auto_start; - - mx_dev->ref = ref; - /* Reset read index */ - mx_dev->read_idx = 0; - - return 0; -} - -static int mx_dbg_sampler_free_resources(struct scsc_service *service, struct mx_dbg_sampler_dev *mx_dev) -{ - if (self_test) - if (mx_dbg_sampler_task) - kthread_stop(mx_dbg_sampler_task); - - scsc_service_mifintrbit_unregister_tohost(service, - mx_dev->info.buffer_info.intr_num); - scsc_mx_service_mifram_free(service, - mx_dev->ref); - return 0; -} - -int mx_dbg_sampler_open(struct inode *inode, struct file *filp) -{ - struct mx_dbg_sampler_dev *mx_dev; - int ret = 0, r; - - mx_dev = container_of(inode->i_cdev, struct mx_dbg_sampler_dev, cdev); - - if (mutex_lock_interruptible(&mx_dev->mutex)) - return -ERESTARTSYS; - - if (mx_dev->in_use) { - SCSC_TAG_ERR(MX_SAMPLER, "Device node already opened. Only one instance allowed. Exit\n"); - ret = -EIO; - goto end; - } - - if (filp->private_data) { - SCSC_TAG_ERR(MX_SAMPLER, "Service already started\n"); - ret = -EIO; - goto end; - } - - filp->private_data = mx_dev; - mx_dev->filp = filp; - /* Clear any remaining error */ - mx_dev->error = NO_ERROR; - - ret = kfifo_alloc(&mx_dev->fifo, kfifo_len, GFP_KERNEL); - if (ret) { - SCSC_TAG_ERR(MX_SAMPLER, "kfifo_alloc failed"); - ret = -EIO; - goto error; - } - - mx_dev->service = scsc_mx_service_open(mx_dev->mx, SCSC_SERVICE_ID_DBG_SAMPLER, &mx_dev->mx_client, &ret); - if (!mx_dev->service) { - SCSC_TAG_ERR(MX_SAMPLER, "Error opening service is NULL\n"); - kfifo_free(&mx_dev->fifo); - ret = -EIO; - goto error; - } - /* Allocate resources */ - ret = mx_dbg_sampler_allocate_resources(mx_dev->service, mx_dev); - if (ret) { - SCSC_TAG_ERR(MX_SAMPLER, "Error Allocating resources\n"); - kfifo_free(&mx_dev->fifo); - r = scsc_mx_service_close(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_close failed %d\n", r); - goto error; - } - - ret = scsc_mx_service_start(mx_dev->service, mx_dev->ref); - if (ret) { - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_start failed\n"); - mx_dbg_sampler_free_resources(mx_dev->service, mx_dev); - kfifo_free(&mx_dev->fifo); - r = scsc_mx_service_close(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_close failed %d\n", r); - goto error; - } - /* WARNING: At this point we may be receiving interrupts from Maxwell */ - - /* Trigger the dummy thread to test the functionality */ - if (self_test) - mx_dbg_sampler_task = kthread_run(mx_dbg_sampler_thread, (void *)mx_dev, "mx_dbg_sampler_thread"); - - SCSC_TAG_INFO(MX_SAMPLER, "%s: Sampling....\n", DRV_NAME); - mx_dev->in_use = true; - mutex_unlock(&mx_dev->mutex); - return 0; -error: - filp->private_data = NULL; - mx_dev->filp = NULL; - mx_dev->service = NULL; -end: - mutex_unlock(&mx_dev->mutex); - return ret; -} - -static ssize_t mx_dbg_sampler_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) -{ - unsigned int copied; - int ret = 0; - struct mx_dbg_sampler_dev *mx_dev; - - mx_dev = filp->private_data; - - if (mutex_lock_interruptible(&mx_dev->mutex)) - return -EINTR; - - /* Check whether the device is in error */ - if (mx_dev->error != NO_ERROR) { - SCSC_TAG_ERR(MX_SAMPLER, "Device in error\n"); - ret = -EIO; - goto end; - } - - while (len) { - if (kfifo_len(&mx_dev->fifo)) { - ret = kfifo_to_user(&mx_dev->fifo, buf, len, &copied); - if (!ret) - ret = copied; - break; - } - - if (filp->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - ret = wait_event_interruptible(mx_dev->read_wait, - !kfifo_is_empty(&mx_dev->fifo)); - if (ret < 0) - break; - } -end: - mutex_unlock(&mx_dev->mutex); - return ret; -} - -static unsigned mx_dbg_sampler_poll(struct file *filp, poll_table *wait) -{ - struct mx_dbg_sampler_dev *mx_dev; - int ret; - - mx_dev = filp->private_data; - - if (mutex_lock_interruptible(&mx_dev->mutex)) - return -EINTR; - - if (mx_dev->error != NO_ERROR) { - ret = POLLERR; - goto end; - } - - poll_wait(filp, &mx_dev->read_wait, wait); - - if (!kfifo_is_empty(&mx_dev->fifo)) { - ret = POLLIN | POLLRDNORM; /* readeable */ - goto end; - } - - ret = POLLOUT | POLLWRNORM; /* writable */ - -end: - mutex_unlock(&mx_dev->mutex); - return ret; -} - -int mx_dbg_sampler_release(struct inode *inode, struct file *filp) -{ - struct mx_dbg_sampler_dev *mx_dev; - unsigned long flags; - int r; - - mx_dev = container_of(inode->i_cdev, struct mx_dbg_sampler_dev, cdev); - - if (mutex_lock_interruptible(&mx_dev->mutex)) - return -EINTR; - - if (mx_dev->filp == NULL) { - SCSC_TAG_ERR(MX_SAMPLER, "Device already closed\n"); - mutex_unlock(&mx_dev->mutex); - return -EIO; - } - - if (mx_dev != filp->private_data) { - SCSC_TAG_ERR(MX_SAMPLER, "Data mismatch\n"); - mutex_unlock(&mx_dev->mutex); - return -EIO; - } - - spin_lock_irqsave(&mx_dev->spinlock, flags); - filp->private_data = NULL; - mx_dev->filp = NULL; - mx_dev->in_use = false; - kfifo_free(&mx_dev->fifo); - spin_unlock_irqrestore(&mx_dev->spinlock, flags); - - if (mx_dev->service) { - r = scsc_mx_service_stop(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_stop failed err: %d\n", r); - mx_dbg_sampler_free_resources(mx_dev->service, mx_dev); - r = scsc_mx_service_close(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_close failed %d\n", r); - - spin_lock_irqsave(&mx_dev->spinlock, flags); - mx_dev->service = NULL; - spin_unlock_irqrestore(&mx_dev->spinlock, flags); - } - - mutex_unlock(&mx_dev->mutex); - SCSC_TAG_INFO(MX_SAMPLER, "%s: Sampling... end. Kfifo_max = %d\n", DRV_NAME, mx_dev->kfifo_max); - return 0; -} - -static const struct file_operations mx_dbg_sampler_fops = { - .owner = THIS_MODULE, - .open = mx_dbg_sampler_open, - .read = mx_dbg_sampler_read, - .release = mx_dbg_sampler_release, - .poll = mx_dbg_sampler_poll, -}; - -void mx_dbg_sampler_probe(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - dev_t devn; - int ret, i = SCSC_MX_DEBUG_INTERFACES; - char dev_name[20]; - long uid = 0; - int minor; - struct mx_dbg_sampler_dev *mx_dev; - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery_in_progress) { - SCSC_TAG_INFO(MX_SAMPLER, "Recovery remove - no recovery in progress\n"); - return; - } - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && recovery_in_progress) { - SCSC_TAG_INFO(MX_SAMPLER, "Recovery probe\n"); - - while (i--) - if (mx_dbg_sampler.devs[i].cdev.dev && mx_dbg_sampler.devs[i].mx) { - mx_dev = &mx_dbg_sampler.devs[i]; - /* This should be never be true - as knod should prevent unloading while - * the service (device node) is open */ - - mx_dev->service = scsc_mx_service_open(mx_dev->mx, SCSC_SERVICE_ID_DBG_SAMPLER, &mx_dev->mx_client, &ret); - if (!mx_dev->service) { - SCSC_TAG_ERR(MX_SAMPLER, "Error opening service is NULL\n"); - } else { - int r; - - ret = scsc_mx_service_start(mx_dev->service, mx_dev->ref); - if (ret) { - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_start failed\n"); - mx_dbg_sampler_free_resources(mx_dev->service, mx_dev); - r = scsc_mx_service_close(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, - "scsc_mx_service_close failed %d\n", r); - } - } - } - recovery_in_progress = 0; - } else { - /* Search for free minors */ - minor = find_first_zero_bit(bitmap_dbg_sampler_minor, SCSC_MX_DEBUG_INTERFACES); - if (minor >= SCSC_MX_DEBUG_INTERFACES) { - SCSC_TAG_ERR(MX_SAMPLER, "minor %d > SCSC_TTY_MINORS\n", minor); - return; - } - -#if 0 - /* TODO GET UID */ - if (kstrtol(dev_uid, 10, &uid)) { - SCSC_TAG_ERR(MX_SAMPLER, "Invalid device uid default to zero\n"); - uid = 0; - } -#endif - - devn = MKDEV(MAJOR(mx_dbg_sampler.device), MINOR(minor)); - - snprintf(dev_name, sizeof(dev_name), "%s_%d_%s", "mx", (int)uid, "debug_sampler"); - - cdev_init(&mx_dbg_sampler.devs[minor].cdev, &mx_dbg_sampler_fops); - mx_dbg_sampler.devs[minor].cdev.owner = THIS_MODULE; - mx_dbg_sampler.devs[minor].cdev.ops = &mx_dbg_sampler_fops; - - ret = cdev_add(&mx_dbg_sampler.devs[minor].cdev, devn, 1); - if (ret) { - mx_dbg_sampler.devs[minor].cdev.dev = 0; - mx_dbg_sampler.devs[minor].dev = NULL; - return; - } - - mx_dbg_sampler.devs[minor].dev = device_create(mx_dbg_sampler.class_mx_dbg_sampler, NULL, mx_dbg_sampler.devs[minor].cdev.dev, NULL, dev_name); - - if (mx_dbg_sampler.devs[minor].dev == NULL) { - SCSC_TAG_ERR(MX_SAMPLER, "dev is NULL\n"); - cdev_del(&mx_dbg_sampler.devs[minor].cdev); - return; - } - - mx_dbg_sampler.devs[minor].mx = mx; - mx_dbg_sampler.devs[minor].mx_client.failure_notification = mx_dbg_sampler_failure_notification; - mx_dbg_sampler.devs[minor].mx_client.stop_on_failure_v2 = mx_dbg_sampler_stop_on_failure; - mx_dbg_sampler.devs[minor].mx_client.failure_reset_v2 = mx_dbg_sampler_failure_reset; - - mutex_init(&mx_dbg_sampler.devs[minor].mutex); - spin_lock_init(&mx_dbg_sampler.devs[minor].spinlock); - mx_dbg_sampler.devs[minor].kfifo_max = 0; - - init_waitqueue_head(&mx_dbg_sampler.devs[minor].read_wait); - - /* Update bit mask */ - set_bit(minor, bitmap_dbg_sampler_minor); - - SCSC_TAG_INFO(MX_SAMPLER, "%s: Ready to start sampling....\n", DRV_NAME); - } -} - -void mx_dbg_sampler_remove(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - int i = SCSC_MX_DEBUG_INTERFACES, r; - struct mx_dbg_sampler_dev *mx_dev; - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery_in_progress) { - SCSC_TAG_INFO(MX_SAMPLER, "Recovery remove - no recovery in progress\n"); - return; - } - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && recovery_in_progress) { - SCSC_TAG_INFO(MX_SAMPLER, "Recovery remove\n"); - - while (i--) - if (mx_dbg_sampler.devs[i].cdev.dev && mx_dbg_sampler.devs[i].mx) { - mx_dev = &mx_dbg_sampler.devs[i]; - /* This should be never be true - as knod should prevent unloading while - * the service (device node) is open */ - if (mx_dbg_sampler.devs[i].service) { - r = scsc_mx_service_stop(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_stop failed err: %d\n", r); - - r = scsc_mx_service_close(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_close failed err: %d\n", r); - } - } - } else { - while (i--) - if (mx_dbg_sampler.devs[i].mx == mx) { - device_destroy(mx_dbg_sampler.class_mx_dbg_sampler, mx_dbg_sampler.devs[i].cdev.dev); - cdev_del(&mx_dbg_sampler.devs[i].cdev); - memset(&mx_dbg_sampler.devs[i].cdev, 0, sizeof(struct cdev)); - mx_dbg_sampler.devs[i].mx = NULL; - clear_bit(i, bitmap_dbg_sampler_minor); - } - } -} - -/* Test client driver registration */ -struct scsc_mx_module_client mx_dbg_sampler_driver = { - .name = "MX client test driver", - .probe = mx_dbg_sampler_probe, - .remove = mx_dbg_sampler_remove, -}; - -/* Test client driver registration */ -static int __init mx_dbg_sampler_init(void) -{ - int ret; - - SCSC_TAG_INFO(MX_SAMPLER, "mx_dbg_sampler INIT; version: %d.%d\n", VER_MAJOR, VER_MINOR); - - ret = alloc_chrdev_region(&mx_dbg_sampler.device, 0, SCSC_MX_DEBUG_INTERFACES, "mx_dbg_sampler_char"); - if (ret) - goto error; - - mx_dbg_sampler.class_mx_dbg_sampler = class_create(THIS_MODULE, DEVICE_NAME); - if (IS_ERR(mx_dbg_sampler.class_mx_dbg_sampler)) { - SCSC_TAG_ERR(MX_SAMPLER, "mx_dbg_sampler class creation failed\n"); - ret = PTR_ERR(mx_dbg_sampler.class_mx_dbg_sampler); - goto error_class; - } - - ret = scsc_mx_module_register_client_module(&mx_dbg_sampler_driver); - if (ret) { - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_module_register_client_module failed: ret=%d\n", ret); - goto error_reg; - } - - return 0; - -error_reg: - class_destroy(mx_dbg_sampler.class_mx_dbg_sampler); -error_class: - unregister_chrdev_region(mx_dbg_sampler.device, SCSC_MX_DEBUG_INTERFACES); -error: - return ret; -} - -/* module level */ -static void __exit mx_dbg_sampler_unload(void) -{ - int i = SCSC_MX_DEBUG_INTERFACES; - unsigned long flags; - struct mx_dbg_sampler_dev *mx_dev; - int r; - - while (i--) - if (mx_dbg_sampler.devs[i].cdev.dev && mx_dbg_sampler.devs[i].mx) { - mx_dev = &mx_dbg_sampler.devs[i]; - /* This should be never be true - as knod should prevent unloading while - * the service (device node) is open */ - if (mx_dbg_sampler.devs[i].service) { - r = scsc_mx_service_stop(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_stop failed err: %d\n", r); - mx_dbg_sampler_free_resources(mx_dev->service, mx_dev); - r = scsc_mx_service_close(mx_dev->service); - if (r) - SCSC_TAG_ERR(MX_SAMPLER, "scsc_mx_service_close failed err: %d\n", r); - - spin_lock_irqsave(&mx_dbg_sampler.devs[i].spinlock, flags); - mx_dbg_sampler.devs[i].filp = NULL; - kfifo_free(&mx_dbg_sampler.devs[i].fifo); - mx_dbg_sampler.devs[i].service = NULL; - spin_unlock_irqrestore(&mx_dev->spinlock, flags); - } - device_destroy(mx_dbg_sampler.class_mx_dbg_sampler, mx_dbg_sampler.devs[i].cdev.dev); - cdev_del(&mx_dbg_sampler.devs[i].cdev); - memset(&mx_dbg_sampler.devs[i].cdev, 0, sizeof(struct cdev)); - mx_dbg_sampler.devs[i].mx = NULL; - clear_bit(i, bitmap_dbg_sampler_minor); - } - class_destroy(mx_dbg_sampler.class_mx_dbg_sampler); - unregister_chrdev_region(mx_dbg_sampler.device, SCSC_MX_DEBUG_INTERFACES); - - SCSC_TAG_INFO(MX_SAMPLER, "mx_dbg_sampler EXIT; version: %d.%d\n", VER_MAJOR, VER_MINOR); -} - -module_init(mx_dbg_sampler_init); -module_exit(mx_dbg_sampler_unload); - -MODULE_DESCRIPTION("Samsung debug sampler Driver"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL and additional rights"); -/* - * MODULE_INFO(version, VER_MAJOR); - * MODULE_INFO(build, SLSI_BUILD_STRING); - * MODULE_INFO(release, SLSI_RELEASE_STRING); - */ diff --git a/drivers/misc/samsung/scsc/mx_dbg_sampler.h b/drivers/misc/samsung/scsc/mx_dbg_sampler.h deleted file mode 100644 index 240601089e01..000000000000 --- a/drivers/misc/samsung/scsc/mx_dbg_sampler.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MX_DBG_SAMPLER_H__ -#define __MX_DBG_SAMPLER_H__ - - -/** - * Debug Sampler DRAM Buffer descriptor. - * - * Initialised by Debug Sampler Driver on AP and passed by - * reference to Debug Sampler (Proxy) on R4 (by reference in - * WLAN config). - * - * Integer fields are LittleEndian. - */ -struct debug_sampler_buffer_info { - /** - * Offset of circular octet buffer w.r.t. shared dram start - */ - uint32_t buf_offset; - - /** - * Circular buffer length (octets, 2^n) - * - * Default = 32KiB default - */ - uint32_t buf_len; - - /** - * Offset of 32bit write index (not wrapped, counts octets) w.r.t. shared dram start - */ - uint32_t write_index_offset; - - /** - * To AP interrupt number (0 – 15) - */ - uint32_t intr_num; -}; - -struct debug_sampler_sample_spec { - /** - * -relative address of Location to sample (usually a register) - * - * Default = 0x00000000 - */ - uint32_t source_addr; - - /** - * Number of significant octets (1,2 or 4) to log (lsbytes from source) - * - * Default = 4 - */ - uint32_t num_bytes; - - /** - * Sampling period. - * - * 0 means as fast as possible (powers of 2 only) - * - * Default = 0 - */ - uint32_t period_usecs; -}; - - -/** - * Debug Sampler Config Structure. - * - * This structure is allocated and initialised by the Debug Sampler driver - * on the AP and passed via the service_start message. - */ -struct debug_sampler_config { - /** - * Config Structure Version (= DBGSAMPLER_CONFIG_VERSION) - * - * Set by driver, checked by service. - */ - uint32_t version; - - /** - * To-host circular buffer desciptor. - */ - struct debug_sampler_buffer_info buffer_info; - - /** - * Init/default sampling specification. - * - * (There is also an API on R4 to allow dynamic specification - * change - e.g. by WLAN service) - */ - struct debug_sampler_sample_spec sample_spec; - - /** - * Start/stop sampling when service is started/stopped? - * - * (There is also an API on R4 to allow dynamic start/stop - * - e.g. by WLAN service) - * - * Default = 0 - */ - uint32_t auto_start; -}; - -struct debug_sampler_align { - - struct debug_sampler_config config __aligned(4); - - u32 index; - - void *mem __aligned(64); - -}; - - -#endif /* __MX_DBG_SAMPLER_H__ */ - - diff --git a/drivers/misc/samsung/scsc/mx_mmap.c b/drivers/misc/samsung/scsc/mx_mmap.c deleted file mode 100644 index e080e764609e..000000000000 --- a/drivers/misc/samsung/scsc/mx_mmap.c +++ /dev/null @@ -1,545 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scsc_mif_abs.h" -#include "mxman.h" -#include "scsc_mx_impl.h" -#include "gdb_transport.h" - -#define DRV_NAME "mx_mmap" -#define DEVICE_NAME "maxwell_mmap" - -#ifndef VM_RESERVED -#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) -#endif - -#define VER_MAJOR 0 -#define VER_MINOR 0 - -#define SCSC_MMAP_NODE 1 -#define SCSC_GDB_NODE 1 -#define SCSC_GDB_DEF_BUF_SZ 64 - -#define SCSC_MAX_INTERFACES (5 * (SCSC_MMAP_NODE + SCSC_GDB_NODE)) - -#define MAX_MEMORY (8 * 1024 * 1024UL) /* maximum memory: this should match MX_DRAM_SIZE_SECTION_1 */ - -DECLARE_BITMAP(bitmap_minor, SCSC_MAX_INTERFACES); - -struct mx_mmap_dev { - /* file pointer */ - struct file *filp; - /* char device */ - struct cdev cdev; - /*device pointer*/ - struct device *dev; - /*mif_abs pointer*/ - struct scsc_mif_abs *mif_abs; - /*mif_abs pointer*/ - struct scsc_mx *mx; - /*mif_abs pointer*/ - struct gdb_transport *gdb_transport; - /*memory cache*/ - void *mem; - /* Associated kfifo */ - struct kfifo fifo; - /* Associated read_wait queue.*/ - wait_queue_head_t read_wait; - /* User count */ - volatile unsigned long lock; -}; - -/** - * SCSC User Space mmap interface (singleton) - */ -static struct { - dev_t device; - struct class *class_mx_mmap; - struct mx_mmap_dev devs[SCSC_MAX_INTERFACES]; /*MMAP NODE + GDB NODE*/ -} mx_mmap; - -int mx_mmap_open(struct inode *inode, struct file *filp) -{ - struct mx_mmap_dev *dev; - - dev = container_of(inode->i_cdev, struct mx_mmap_dev, cdev); - - SCSC_TAG_INFO(MX_MMAP, "open %p\n", filp); - - filp->private_data = dev; - - return 0; -} - -/* - * This function maps the contiguous device mapped area - * to user space. This is specfic to device which is called though fd. - */ -int mx_mmap_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int err; - struct mx_mmap_dev *mx_dev; - uintptr_t pfn = 0; - - if (vma->vm_end - vma->vm_start > MAX_MEMORY) { - SCSC_TAG_ERR(MX_MMAP, "Incorrect mapping size %ld, should be less than %ld\n", - vma->vm_end - vma->vm_start, MAX_MEMORY); - err = -EINVAL; - } - mx_dev = filp->private_data; - - /* Get the memory */ - mx_dev->mem = mx_dev->mif_abs->get_mifram_ptr(mx_dev->mif_abs, 0); - - if (!mx_dev->mem) - return -ENODEV; - - /* Get page frame number from virtual abstraction layer */ - pfn = mx_dev->mif_abs->get_mifram_pfn(mx_dev->mif_abs); - - /* remap kernel memory to userspace */ - err = remap_pfn_range(vma, vma->vm_start, pfn, - vma->vm_end - vma->vm_start, vma->vm_page_prot); - - return err; -} - - - -int mx_mmap_release(struct inode *inode, struct file *filp) -{ - SCSC_TAG_INFO(MX_MMAP, "close %p\n", filp); - - /* TODO : Unmap pfn_range */ - return 0; -} - -static const struct file_operations mx_mmap_fops = { - .owner = THIS_MODULE, - .open = mx_mmap_open, - .mmap = mx_mmap_mmap, - .release = mx_mmap_release, -}; - -int mx_gdb_open(struct inode *inode, struct file *filp) -{ - struct mx_mmap_dev *mx_dev; - int ret; - - mx_dev = container_of(inode->i_cdev, struct mx_mmap_dev, cdev); - - SCSC_TAG_INFO(MX_MMAP, "open %p\n", filp); - - if (!mx_dev->gdb_transport) { - SCSC_TAG_ERR(MX_MMAP, "no transport %p\n", filp); - return -ENODEV; - } - - if (test_and_set_bit_lock(0, &mx_dev->lock)) { - SCSC_TAG_ERR(MX_MMAP, "already open %p\n", filp); - return -EBUSY; - } - - /* Prevent channel teardown while client has open */ - mutex_lock(&mx_dev->gdb_transport->channel_open_mutex); - - filp->private_data = mx_dev; - mx_dev->filp = filp; - ret = kfifo_alloc(&mx_dev->fifo, GDB_TRANSPORT_BUF_LENGTH, GFP_KERNEL); - if (ret) { - mutex_unlock(&mx_dev->gdb_transport->channel_open_mutex); - clear_bit_unlock(0, &mx_dev->lock); - return -ENOMEM; - } - - return 0; -} - -static ssize_t mx_gdb_write(struct file *filp, const char __user *ubuf, size_t len, loff_t *offset) -{ - struct mx_mmap_dev *mx_dev; - char *wbuf = NULL, *lbuf = NULL, buf[SCSC_GDB_DEF_BUF_SZ] = {}; - - mx_dev = filp->private_data; - /* When write_req do NOT fit inside the auto array just dyn-alloc */ - if (len <= SCSC_GDB_DEF_BUF_SZ) { - wbuf = buf; - } else { - wbuf = kzalloc(len, GFP_KERNEL); - if (!wbuf) - return -ENOMEM; - /* Use the freshly dyn-allocated buf */ - SCSC_TAG_DEBUG(MX_MMAP, "Allocated GDB write dyn-buffer [%zd]\n", len); - lbuf = wbuf; - } - - if (copy_from_user(wbuf, ubuf, len)) { - kfree(lbuf); - return -EINVAL; - } - - gdb_transport_send(mx_dev->gdb_transport, (void *)wbuf, len); - kfree(lbuf); - - return len; -} - -static ssize_t mx_gdb_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) -{ - int ret = 0; - unsigned int copied; - struct mx_mmap_dev *mx_dev; - - mx_dev = filp->private_data; - - while (len) { - if (kfifo_len(&mx_dev->fifo)) { - ret = kfifo_to_user(&mx_dev->fifo, buf, len, &copied); - if (!ret) { - SCSC_TAG_DEBUG(MX_MMAP, "Copied %d bytes to user.\n", copied); - ret = copied; - } - break; - } - - if (filp->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - ret = wait_event_interruptible(mx_dev->read_wait, - !kfifo_is_empty(&mx_dev->fifo)); - if (ret < 0) - break; - } - - return ret; -} - -void gdb_read_callback(const void *message, size_t length, void *data) -{ - struct mx_mmap_dev *mx_dev = (struct mx_mmap_dev *)data; - int ret; - - if (mx_dev->filp) { - if (kfifo_avail(&mx_dev->fifo) >= length) { - ret = kfifo_in(&mx_dev->fifo, message, length); - if (ret != length) { - SCSC_TAG_ERR(MX_MMAP, "Unable to push into Kfifo Buffer\n"); - return; - } - SCSC_TAG_DEBUG(MX_MMAP, "Buffered %zu bytes\n", length); - } else { - SCSC_TAG_ERR(MX_MMAP, "Kfifo Buffer Overflow\n"); - return; - } - - wake_up_interruptible(&mx_dev->read_wait); - } else - SCSC_TAG_ERR(MX_MMAP, "Device is closed. Dropping %zu octets\n", - length); -} - -static unsigned int mx_gdb_poll(struct file *filp, poll_table *wait) -{ - struct mx_mmap_dev *mx_dev; - - mx_dev = filp->private_data; - - poll_wait(filp, &mx_dev->read_wait, wait); - - if (!kfifo_is_empty(&mx_dev->fifo)) - return POLLIN | POLLRDNORM; /* readeable */ - - return POLLOUT | POLLWRNORM; /* writable */ -} - -int mx_gdb_release(struct inode *inode, struct file *filp) -{ - struct mx_mmap_dev *mx_dev; - - mx_dev = container_of(inode->i_cdev, struct mx_mmap_dev, cdev); - - SCSC_TAG_INFO(MX_MMAP, "close %p\n", filp); - - if (mx_dev->filp == NULL) { - SCSC_TAG_ERR(MX_MMAP, "Device already closed\n"); - return -EIO; - } - - if (mx_dev != filp->private_data) { - SCSC_TAG_ERR(MX_MMAP, "Data mismatch\n"); - return -EIO; - } - - - clear_bit_unlock(0, &mx_dev->lock); - - filp->private_data = NULL; - mx_dev->filp = NULL; - kfifo_free(&mx_dev->fifo); - - mutex_unlock(&mx_dev->gdb_transport->channel_open_mutex); - - return 0; -} - -static const struct file_operations mx_gdb_fops = { - .owner = THIS_MODULE, - .open = mx_gdb_open, - .write = mx_gdb_write, - .read = mx_gdb_read, - .release = mx_gdb_release, - .poll = mx_gdb_poll, -}; - -/* - * Receive handler for messages from the FW along the maxwell management transport - */ -void client_gdb_probe(struct gdb_transport_client *gdb_client, struct gdb_transport *gdb_transport, char *dev_uid) -{ - dev_t devn; - int ret; - char dev_name[20]; - struct mx_mmap_dev *mx_dev; - long uid = 0; - int minor; - - /************/ - /* GDB node */ - /************/ - /* Search for free minors */ - minor = find_first_zero_bit(bitmap_minor, SCSC_MAX_INTERFACES); - - if (minor >= SCSC_MAX_INTERFACES) { - SCSC_TAG_ERR(MX_MMAP, "minor %d > SCSC_TTY_MINORS\n", minor); - return; - } - - if (kstrtol(dev_uid, 10, &uid)) { - SCSC_TAG_ERR(MX_MMAP, "Invalid device uid default to zero\n"); - uid = 0; - } - - devn = MKDEV(MAJOR(mx_mmap.device), MINOR(minor)); - - if (gdb_transport->type == GDB_TRANSPORT_M4) - snprintf(dev_name, sizeof(dev_name), "%s_%d_%s", "mx", (int)uid, "m4_gdb"); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - else if (gdb_transport->type == GDB_TRANSPORT_M4_1) - snprintf(dev_name, sizeof(dev_name), "%s_%d_%s", "mx", (int)uid, "m4_1_gdb"); -#endif - else - snprintf(dev_name, sizeof(dev_name), "%s_%d_%s", "mx", (int)uid, "r4_gdb"); - - cdev_init(&mx_mmap.devs[minor].cdev, &mx_gdb_fops); - mx_mmap.devs[minor].cdev.owner = THIS_MODULE; - mx_mmap.devs[minor].cdev.ops = &mx_gdb_fops; - - ret = cdev_add(&mx_mmap.devs[minor].cdev, devn, 1); - if (ret) { - SCSC_TAG_ERR(MX_MMAP, "cdev_add failed for device %s\n", dev_name); - mx_mmap.devs[minor].cdev.dev = 0; - mx_mmap.devs[minor].dev = NULL; - return; - } - - mx_mmap.devs[minor].dev = device_create(mx_mmap.class_mx_mmap, NULL, mx_mmap.devs[minor].cdev.dev, NULL, dev_name); - - if (mx_mmap.devs[minor].dev == NULL) { - cdev_del(&mx_mmap.devs[minor].cdev); - return; - } - - mx_dev = &mx_mmap.devs[minor]; - mx_mmap.devs[minor].gdb_transport = gdb_transport; - - gdb_transport_register_channel_handler(gdb_transport, gdb_read_callback, (void *)mx_dev); - init_waitqueue_head(&mx_mmap.devs[minor].read_wait); - - /* Update bit mask */ - set_bit(minor, bitmap_minor); -} - -void client_gdb_remove(struct gdb_transport_client *gdb_client, struct gdb_transport *gdb_transport) -{ - int i = SCSC_MAX_INTERFACES; - - while (i--) - if (mx_mmap.devs[i].gdb_transport == gdb_transport) { - device_destroy(mx_mmap.class_mx_mmap, mx_mmap.devs[i].cdev.dev); - cdev_del(&mx_mmap.devs[i].cdev); - memset(&mx_mmap.devs[i].cdev, 0, sizeof(struct cdev)); - mx_mmap.devs[i].gdb_transport = NULL; - clear_bit(i, bitmap_minor); - } -} - -/* Test client driver registration */ -struct gdb_transport_client client_gdb_driver = { - .name = "GDB client driver", - .probe = client_gdb_probe, - .remove = client_gdb_remove, -}; - -void scsc_mx_mmap_module_probe(struct scsc_mif_mmap_driver *abs_driver, struct scsc_mif_abs *mif_abs) -{ - dev_t devn; - int ret; - char dev_name[20]; - char *dev_uid; - long uid = 0; - int minor = 0; - - /* Search for free minors */ - minor = find_first_zero_bit(bitmap_minor, SCSC_MAX_INTERFACES); - - if (minor >= SCSC_MAX_INTERFACES) { - SCSC_TAG_ERR(MX_MMAP, "minor %d > SCSC_TTY_MINORS\n", minor); - return; - } - - /*************/ - /* MMAP node */ - /*************/ - dev_uid = mif_abs->get_uid(mif_abs); - if (kstrtol(dev_uid, 10, &uid)) - uid = 0; - - devn = MKDEV(MAJOR(mx_mmap.device), MINOR(minor)); - snprintf(dev_name, sizeof(dev_name), "%s_%d_%s", "mx", (int)uid, "mmap"); - - cdev_init(&mx_mmap.devs[minor].cdev, &mx_mmap_fops); - mx_mmap.devs[minor].cdev.owner = THIS_MODULE; - mx_mmap.devs[minor].cdev.ops = &mx_mmap_fops; - - ret = cdev_add(&mx_mmap.devs[minor].cdev, devn, 1); - if (ret) { - SCSC_TAG_ERR(MX_MMAP, "cdev_add failed for device %s\n", dev_name); - mx_mmap.devs[minor].cdev.dev = 0; - mx_mmap.devs[minor].dev = NULL; - return; - } - - mx_mmap.devs[minor].dev = device_create(mx_mmap.class_mx_mmap, NULL, mx_mmap.devs[minor].cdev.dev, NULL, dev_name); - - if (mx_mmap.devs[minor].dev == NULL) { - cdev_del(&mx_mmap.devs[minor].cdev); - return; - } - - mx_mmap.devs[minor].mif_abs = mif_abs; - - mx_mmap.devs[minor].mem = mif_abs->get_mifram_ptr(mif_abs, 0); - - /* Update bit mask */ - set_bit(minor, bitmap_minor); -} - - -void scsc_mx_mmap_module_remove(struct scsc_mif_abs *mif_abs) -{ - int i = SCSC_MAX_INTERFACES; - - while (i--) - if (mx_mmap.devs[i].mif_abs == mif_abs) { - device_destroy(mx_mmap.class_mx_mmap, mx_mmap.devs[i].cdev.dev); - cdev_del(&mx_mmap.devs[i].cdev); - memset(&mx_mmap.devs[i].cdev, 0, sizeof(struct cdev)); - mx_mmap.devs[i].mif_abs = NULL; - clear_bit(i, bitmap_minor); - } -} - -static struct scsc_mif_mmap_driver mx_module_mmap_if = { - .name = "Maxwell mmap Driver", - .probe = scsc_mx_mmap_module_probe, - .remove = scsc_mx_mmap_module_remove, -}; - -static int __init mx_mmap_init(void) -{ - int ret; - - SCSC_TAG_INFO(MX_MMAP, "mx_mmap INIT; version: %d.%d\n", VER_MAJOR, VER_MINOR); - - - ret = alloc_chrdev_region(&mx_mmap.device, 0, SCSC_MAX_INTERFACES, "mx_mmap_char"); - if (ret) - goto error; - - mx_mmap.class_mx_mmap = class_create(THIS_MODULE, DEVICE_NAME); - if (IS_ERR(mx_mmap.class_mx_mmap)) { - ret = PTR_ERR(mx_mmap.class_mx_mmap); - goto error_class; - } - - scsc_mif_mmap_register(&mx_module_mmap_if); - - ret = gdb_transport_register_client(&client_gdb_driver); - if (ret) - SCSC_TAG_ERR(MX_MMAP, "scsc_mx_module_register_client_module failed: r=%d\n", ret); - - - return 0; - -error_class: - unregister_chrdev_region(mx_mmap.device, SCSC_MAX_INTERFACES); -error: - return ret; -} - -static void __exit mx_mmap_cleanup(void) -{ - int i = SCSC_MAX_INTERFACES; - - while (i--) - if (mx_mmap.devs[i].cdev.dev) { - device_destroy(mx_mmap.class_mx_mmap, mx_mmap.devs[i].cdev.dev); - cdev_del(&mx_mmap.devs[i].cdev); - memset(&mx_mmap.devs[i].cdev, 0, sizeof(struct cdev)); - clear_bit(i, bitmap_minor); - } - class_destroy(mx_mmap.class_mx_mmap); - unregister_chrdev_region(mx_mmap.device, SCSC_MAX_INTERFACES); - SCSC_TAG_INFO(MX_MMAP, "mx_mmap EXIT; version: %d.%d\n", VER_MAJOR, VER_MINOR); - - gdb_transport_unregister_client(&client_gdb_driver); - /* Notify lower layers that we are unloading */ - scsc_mif_mmap_unregister(&mx_module_mmap_if); -} - -module_init(mx_mmap_init); -module_exit(mx_mmap_cleanup); - -MODULE_DESCRIPTION("Samsung MMAP/GDB Driver"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL and additional rights"); -/* - * MODULE_INFO(version, VER_MAJOR); - * MODULE_INFO(build, SLSI_BUILD_STRING); - * MODULE_INFO(release, SLSI_RELEASE_STRING); - */ diff --git a/drivers/misc/samsung/scsc/mxconf.h b/drivers/misc/samsung/scsc/mxconf.h deleted file mode 100644 index 8fa520c92621..000000000000 --- a/drivers/misc/samsung/scsc/mxconf.h +++ /dev/null @@ -1,188 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * mx140 Infrastructure Configuration Structure. - * - * Used to pass configuration data from AP to R4 infrastructure - * on Maxwell Subsystem startup. - * - * Notes: - * - * - All multi-octet integers shall be stored LittleEndian. - * - * - All location fields ("*_loc") are 32 bit octet offsets w.r.t. the R4 - * address map. They can therefore refer to DRAM memory or Mailbox registers. - * - * - "typedefs" are avoided to allow inclusion in linux source code. - */ -#ifndef MXCONF_H__ -#define MXCONF_H__ - -/* Uses */ - -/* It appears that due to the previous syntax "__packed struct foo" used in this - * header, the structures here don't actually get packed. Clang warns that - * that syntax is ignored. But correcting it causes a misalignment with FW. - * The __MXPACKED macro is used to stop packing the structures in this - * header until we've investigated further. - */ -#define __MXPACKED /* TODO: HACK - don't actually pack! */ - -/* Definitions */ - -/** - * Config structure magic number. - * - * The AP writes this value and the R4 checks it to trap endian mismatches. - */ -#define MXCONF_MAGIC 0x79828486 - -/** - * Config structure version - * - * The AP writes these values and the R4 checks them to trap config structure - * mismatches. - */ -#define MXCONF_VERSION_MAJOR 0 -#define MXCONF_VERSION_MINOR 5 /* For fleximac moredump */ - -/* Types */ - -/** - * Maxwell Circular Packet Buffer Configuration. - */ -struct mxcbufconf { - scsc_mifram_ref buffer_loc; /**< Location of allocated buffer in DRAM */ - uint32_t num_packets; /**< Total number of packets that can be stored in the buffer */ - uint32_t packet_size; /**< Size of each individual packet within the buffer */ - scsc_mifram_ref read_index_loc; /**< Location of 32bit read index in DRAM or Mailbox */ - scsc_mifram_ref write_index_loc; /**< Location of 32bit write index */ -} __MXPACKED; - -/** - * Maxwell Management Simplex Stream Configuration - * - * A circular buffer plus a pair of R/W signaling bits. - */ -struct mxstreamconf { - /** Circular Packet Buffer configuration */ - struct mxcbufconf buf_conf; - - /** Allocated MIF Interrupt Read Bit Index */ - uint8_t read_bit_idx; - - /** Allocated MIF Interrupt Write Bit Index */ - uint8_t write_bit_idx; -} __MXPACKED; - -/** - * Maxwell Management Transport Configuration - * - * A pair of simplex streams. - */ -struct mxtransconf { - struct mxstreamconf to_ap_stream_conf; - struct mxstreamconf from_ap_stream_conf; -} __MXPACKED; - -/** - * Maxwell Infrastructure Configuration Version - */ -struct mxconfversion { - uint16_t major; - uint16_t minor; -} __MXPACKED; - -/** - * Mxlog Event Buffer Configuration. - * - * A circular buffer. Size must be a multiple of 2. - */ -struct mxlogconf -{ - struct mxstreamconf stream_conf; -} __MXPACKED; - - -/** - * Maxwell Infrastructure Configuration Override (HCF block) - */ -struct mxmibref { - uint32_t offset; - uint32_t size; -} __MXPACKED; - - -/** - * Maxwell Infrastructure Configuration - */ -struct mxconf { - /** - * Config Magic Number - * - * Always 1st field in config. - */ - uint32_t magic; - - /** - * Config Version. - * - * Always second field in config. - */ - struct mxconfversion version; - - /** - * MX Management Message Transport Configuration. - */ - struct mxtransconf mx_trans_conf; - - /** - * MX Management GDB Message Transport Configuration. - */ - /* Cortex-R4 channel */ - struct mxtransconf mx_trans_conf_gdb_r4; - /* Cortex-M4 channel */ - struct mxtransconf mx_trans_conf_gdb_m4; - - /** - * Mxlog Event Buffer Configuration. - */ - struct mxlogconf mxlogconf; - - /* FROM MINOR_2 */ - - /** - * SOC HW revision override from host - */ - uint32_t soc_revision; - - /* FROM MINOR_3 */ - - /** - * Setup flags - */ -#define MXCONF_FLAGS_FM_ON (BIT(0)) /* FM already on */ - uint32_t flags; - - /* FROM MINOR_4 */ - - /** - * Common HCF offset - */ - struct mxmibref fwconfig; - - /* FROM MINOR_5 */ - - /* Fleximac Cortex-M3_1 piggy back as M4 channel. - * (Driver must initialise from-ap buffer address to 0 - * if channel is not in use). - */ - struct mxtransconf mx_trans_conf_gdb_m4_1; - -} __MXPACKED; - -#endif /* MXCONF_H__ */ diff --git a/drivers/misc/samsung/scsc/mxfwconfig.c b/drivers/misc/samsung/scsc/mxfwconfig.c deleted file mode 100644 index c724a321362b..000000000000 --- a/drivers/misc/samsung/scsc/mxfwconfig.c +++ /dev/null @@ -1,224 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include - -#include "mxfwconfig.h" -#include "miframman.h" -#include "scsc_mx_impl.h" -#include "mxconf.h" - -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif - -#define MXFWCONFIG_CFG_SUBDIR "common" -#define MXFWCONFIG_CFG_FILE_HW "common.hcf" -#define MXFWCONFIG_CFG_FILE_SW "common_sw.hcf" - -static void mxfwconfig_get_dram_ref(struct scsc_mx *mx, struct mxmibref *cfg_ref); - -/* Load config into non-shared DRAM */ -static int mxfwconfig_load_cfg(struct scsc_mx *mx, struct mxfwconfig *cfg, const char *filename) -{ - int r = 0; - u32 i; - - if (cfg->configs >= SCSC_MX_MAX_COMMON_CFG) { - SCSC_TAG_ERR(MX_CFG, "Too many common config files (%u)\n", cfg->configs); - return -E2BIG; - } - - i = cfg->configs++; /* Claim next config slot */ - - /* Load config file from file system into DRAM */ - r = mx140_file_request_conf(mx, &cfg->config[i].fw, MXFWCONFIG_CFG_SUBDIR, filename); - if (r) - return r; - - /* Initial size of file */ - cfg->config[i].cfg_len = cfg->config[i].fw->size; - cfg->config[i].cfg_data = cfg->config[i].fw->data; - - /* Validate file in DRAM */ - if (cfg->config[i].cfg_len >= MX_COMMON_HCF_HDR_SIZE && /* Room for header */ - /*(cfg->config[i].cfg[6] & 0xF0) == 0x10 && */ /* Curator subsystem */ - cfg->config[i].cfg_data[7] == 1) { /* First file format */ - int j; - - cfg->config[i].cfg_hash = 0; - - /* Calculate hash */ - for (j = 0; j < MX_COMMON_HASH_SIZE_BYTES; j++) { - cfg->config[i].cfg_hash = - (cfg->config[i].cfg_hash << 8) | cfg->config[i].cfg_data[j + MX_COMMON_HASH_OFFSET]; - } - - SCSC_TAG_INFO(MX_CFG, "CFG hash: 0x%.04x\n", cfg->config[i].cfg_hash); - - /* All good - consume header and continue */ - cfg->config[i].cfg_len -= MX_COMMON_HCF_HDR_SIZE; - cfg->config[i].cfg_data += MX_COMMON_HCF_HDR_SIZE; - } else { - SCSC_TAG_ERR(MX_CFG, "Invalid HCF header size %zu\n", cfg->config[i].cfg_len); - - /* Caller must call mxfwconfig_unload_cfg() to release the buffer */ - return -EINVAL; - } - - /* Running shtotal payload */ - cfg->shtotal += cfg->config[i].cfg_len; - - SCSC_TAG_INFO(MX_CFG, "Loaded common config %s, size %zu, payload size %zu, shared dram total %zu\n", - filename, cfg->config[i].fw->size, cfg->config[i].cfg_len, cfg->shtotal); - - return r; -} - -/* Unload config from non-shared DRAM */ -static int mxfwconfig_unload_cfg(struct scsc_mx *mx, struct mxfwconfig *cfg, u32 index) -{ - if (index >= SCSC_MX_MAX_COMMON_CFG) { - SCSC_TAG_ERR(MX_CFG, "Out of range index (%u)\n", index); - return -E2BIG; - } - - if (cfg->config[index].fw) { - SCSC_TAG_DBG3(MX_CFG, "Unload common config %u\n", index); - - mx140_file_release_conf(mx, cfg->config[index].fw); - - cfg->config[index].fw = NULL; - cfg->config[index].cfg_data = NULL; - cfg->config[index].cfg_len = 0; - } - - return 0; -} - -/* - * Load Common config files - */ -int mxfwconfig_load(struct scsc_mx *mx, struct mxmibref *cfg_ref) -{ - struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); - struct miframman *miframman = scsc_mx_get_ramman(mx); - int r; - u32 i; - u8 *dest; - - /* HW file is optional */ - r = mxfwconfig_load_cfg(mx, cfg, MXFWCONFIG_CFG_FILE_HW); - if (r) - goto done; - - /* SW file is optional, but not without HW file */ - r = mxfwconfig_load_cfg(mx, cfg, MXFWCONFIG_CFG_FILE_SW); - if (r == -EINVAL) { - /* If SW file is corrupt, abandon both HW and SW */ - goto done; - } - - /* Allocate shared DRAM */ - cfg->shdram = miframman_alloc(miframman, cfg->shtotal, 4, MIFRAMMAN_OWNER_COMMON); - if (!cfg->shdram) { - SCSC_TAG_ERR(MX_CFG, "MIF alloc failed for %zu octets\n", cfg->shtotal); - r = -ENOMEM; - goto done; - } - - /* Copy files into shared DRAM */ - for (i = 0, dest = (u8 *)cfg->shdram; - i < cfg->configs; - i++) { - /* Add to shared DRAM block */ - memcpy(dest, cfg->config[i].cfg_data, cfg->config[i].cfg_len); - dest += cfg->config[i].cfg_len; - } - -done: - /* Release the files from non-shared DRAM */ - for (i = 0; i < cfg->configs; i++) - mxfwconfig_unload_cfg(mx, cfg, i); - - /* Configs abandoned on error */ - if (r) - cfg->configs = 0; - - /* Pass offset of common HCF data. - * FW must ignore if zero length, so set up even if we loaded nothing. - */ - mxfwconfig_get_dram_ref(mx, cfg_ref); - - return r; -} - -/* - * Unload Common config data - */ -void mxfwconfig_unload(struct scsc_mx *mx) -{ - struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); - struct miframman *miframman = scsc_mx_get_ramman(mx); - - /* Free config block in shared DRAM */ - if (cfg->shdram) { - SCSC_TAG_INFO(MX_CFG, "Free common config %zu bytes shared DRAM\n", cfg->shtotal); - - miframman_free(miframman, cfg->shdram); - - cfg->configs = 0; - cfg->shtotal = 0; - cfg->shdram = NULL; - } -} - -/* - * Get ref (offset) of config block in shared DRAM - */ -static void mxfwconfig_get_dram_ref(struct scsc_mx *mx, struct mxmibref *cfg_ref) -{ - struct mxfwconfig *mxfwconfig = scsc_mx_get_mxfwconfig(mx); - struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(mx); - - if (!mxfwconfig->shdram) { - cfg_ref->offset = (scsc_mifram_ref)0; - cfg_ref->size = 0; - } else { - mif->get_mifram_ref(mif, mxfwconfig->shdram, &cfg_ref->offset); - cfg_ref->size = (uint32_t)mxfwconfig->shtotal; - } - - SCSC_TAG_INFO(MX_CFG, "cfg_ref: 0x%x, size %u\n", cfg_ref->offset, cfg_ref->size); -} - -/* - * Init config file module - */ -int mxfwconfig_init(struct scsc_mx *mx) -{ - struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); - - cfg->configs = 0; - cfg->shtotal = 0; - cfg->shdram = NULL; - - return 0; -} - -/* - * Exit config file module - */ -void mxfwconfig_deinit(struct scsc_mx *mx) -{ - struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); - - /* Leaked memory? */ - WARN_ON(cfg->configs > 0); - WARN_ON(cfg->shdram); -} - diff --git a/drivers/misc/samsung/scsc/mxfwconfig.h b/drivers/misc/samsung/scsc/mxfwconfig.h deleted file mode 100644 index f24d44c599ef..000000000000 --- a/drivers/misc/samsung/scsc/mxfwconfig.h +++ /dev/null @@ -1,35 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MXFWCONFIG_H -#define __MXFWCONFIG_H - -#define SCSC_MX_MAX_COMMON_CFG 2 -#define MX_COMMON_HCF_HDR_SIZE 8 -#define MX_COMMON_HASH_SIZE_BYTES 2 /* Hash will be contained in a uint32 */ -#define MX_COMMON_HASH_OFFSET 4 - -struct mxfwconfig { - u32 configs; /* Number of files */ - void *shdram; /* Combined payload in shared DRAM */ - size_t shtotal; /* Size of combined payload in shared DRAM */ - - struct { - const struct firmware *fw; /* File image in DRAM */ - const u8 *cfg_data; /* Payload in DRAM */ - size_t cfg_len; /* Length of payload */ - u32 cfg_hash; /* ID hash */ - } config[SCSC_MX_MAX_COMMON_CFG]; -}; - -struct mxmibref; - -int mxfwconfig_init(struct scsc_mx *mx); -void mxfwconfig_deinit(struct scsc_mx *mx); -int mxfwconfig_load(struct scsc_mx *mx, struct mxmibref *cfg_ref); -void mxfwconfig_unload(struct scsc_mx *mx); - -#endif // __MXFWCONFIG_H diff --git a/drivers/misc/samsung/scsc/mxlog.c b/drivers/misc/samsung/scsc/mxlog.c deleted file mode 100644 index e15afba58cfa..000000000000 --- a/drivers/misc/samsung/scsc/mxlog.c +++ /dev/null @@ -1,410 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include "scsc_mx_impl.h" -#include "mxmgmt_transport.h" -#include "mxlog_transport.h" -#include "fwhdr.h" -#include "mxlog.h" - -/* - * Receive handler for messages from the FW along the maxwell management transport - */ -static inline void mxlog_phase4_message_handler(const void *message, - size_t length, u32 level, - void *data) -{ - unsigned char *buf = (unsigned char *)message; - - SCSC_TAG_LVL(MX_FW, level, SCSC_PREFIX"%d: %s\n", (int)length, buf); -} - -/** - * This function is used to parse a NULL terminated format string - * and report on the provided output bitmaps smap/lmap which args - * are 'long' and which are signed.. - * - * We will care only about length and specifier fields - * - * %[flags][width][.precision][length]specifier - * - * and since flags width and .precision are represented - * by NON chars, we will grossly compare simply against an 'A', - * because we are NOT trying to make a full sanity check here BUT only - * to search for long and signed values to provide the proper cast. - * - * Supporting: - * - ESCAPES %%ld - * - * - %x %X %d %ld %lld %i %li %lli %u %lu %llu %hd %hhd %hu %hhu - * - * NOT supporting: - * - %s -> MARKED AS UNSUPPORTED - */ -static inline void build_len_sign_maps(char *fmt, u32 *smap, u32 *lmap, - u32 *strmap) -{ - u32 p = 0; - char *s = fmt; - bool escaping = false; - - if (!s) - return; - for (; *s != '\0'; ++s) { - /* Skip any escaped fmtstring like %%d and move on */ - if (escaping) { - if (*s == ' ') - escaping = false; - continue; - } - if (*s != '%') - continue; - /* Start escape seq ... */ - if (*(s + 1) == '%') { - escaping = true; - continue; - } - /* skip [flags][width][.precision] if any */ - for (; *++s < 'A';) - ; - if (*s == 'l') { - *lmap |= (1 << p); - /* %lld ? skip */ - if (*++s == 'l') - s++; - } else if (*s == 'h') { - /* just skip h modifiers */ - /* hhd ? */ - if (*++s == 'h') - s++; - } - if (*s == 'd' || *s == 'i') - *smap |= (1 << p); - else if (*s == 's') - *strmap |= (1 << p); - p++; - } -} - -/** - * The binary protocol described at: - * - * http://wiki/Maxwell_common_firmware/Mxlog#Phase_5_:_string_decoded_on_the_host - * - * states that we'd receive the following record content on each mxlog - * message from FW, where: - * - * - each element is a 32bit word - * - 1st element is a record header - * - len = number of elements following the first element - * - * | 1st | 2nd | 3rd | 4th | 5th | 6th - * ----------------------------------------------------------- - * | sync|lvl|len || tstamp || offset || arg1 || arg2 || arg3. - * ----------------------------------------------------------- - * | e l o g m s g | - * - * BUT NOTE THAT: here we DO NOT receive 1st header element BUT - * instead we got: - * @message: pointer to 2nd element - * @length: in bytes of the message (so starting from 2nd element) and - * including tstamp and offset elements: we must calculate - * num_args accordingly. - * @level: the debug level already remapped from FW to Kernel namespace - */ -static inline void mxlog_phase5_message_handler(const void *message, - size_t length, u32 level, - void *data) -{ - struct mxlog *mxlog = (struct mxlog *)data; - struct mxlog_event_log_msg *elogmsg = - (struct mxlog_event_log_msg *)message; - - if (length < MINIMUM_MXLOG_MSG_LEN_BYTES) - return; - if (mxlog && elogmsg) { - int num_args = 0; - char spare[MAX_SPARE_FMT + TSTAMP_LEN] = {}; - char *fmt = NULL; - size_t fmt_sz = 0; - u32 smap = 0, lmap = 0, strmap = 0; - u32 *args = NULL; - - /* Check OFFSET sanity... beware of FW guys :D ! */ - if (elogmsg->offset >= MXLS_SZ(mxlog)) { - SCSC_TAG_ERR(MX_FW, - "Received fmtstr OFFSET(%d) is OUT OF range(%zd)...skip..\n", - elogmsg->offset, MXLS_SZ(mxlog)); - return; - } - args = (u32 *)(elogmsg + 1); - num_args = - (length - MINIMUM_MXLOG_MSG_LEN_BYTES) / - MXLOG_ELEMENT_SIZE; - fmt = (char *)(MXLS_DATA(mxlog) + elogmsg->offset); - /* Avoid being fooled by a NON NULL-terminated strings too ! */ - fmt_sz = strnlen(fmt, MXLS_SZ(mxlog) - elogmsg->offset); - if (fmt_sz >= MAX_SPARE_FMT - 1) { - SCSC_TAG_ERR(MX_FW, - "UNSUPPORTED message length %zd ... truncated.\n", - fmt_sz); - fmt_sz = MAX_SPARE_FMT - 2; - } - /* Pre-Process fmt string to be able to do proper casting */ - if (num_args) - build_len_sign_maps(fmt, &smap, &lmap, &strmap); - - /* Add FW provided tstamp on front and proper \n at - * the end when needed - */ - snprintf(spare, MAX_SPARE_FMT + TSTAMP_LEN - 2, SCSC_PREFIX"%08X %s%c", - elogmsg->timestamp, fmt, - (fmt[fmt_sz] != '\n') ? '\n' : '\0'); - fmt = spare; - - switch (num_args) { - case 0: - SCSC_TAG_LVL(MX_FW, level, fmt); - break; - case 1: - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - case 2: - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[1], 1, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - case 3: - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[1], 1, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[2], 2, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - case 4: - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[1], 1, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[2], 2, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[3], 3, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - case 5: - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[1], 1, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[2], 2, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[3], 3, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[4], 4, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - case 6: - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[1], 1, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[2], 2, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[3], 3, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[4], 4, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[5], 5, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - case 7: - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[1], 1, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[2], 2, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[3], 3, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[4], 4, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[5], 5, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[6], 6, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - case 8: - default: - if (num_args > MAX_MX_LOG_ARGS) - SCSC_TAG_ERR(MX_FW, - "MXLOG: Too many args:%d ... print only first %d\n", - num_args, MAX_MX_LOG_ARGS); - SCSC_TAG_LVL(MX_FW, level, fmt, - MXLOG_CAST(args[0], 0, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[1], 1, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[2], 2, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[3], 3, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[4], 4, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[5], 5, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[6], 6, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog)), - MXLOG_CAST(args[7], 7, smap, lmap, strmap, - MXLS_DATA(mxlog), MXLS_SZ(mxlog))); - break; - } - } -} - -/* A generic message handler to multiplex between phases */ -static void mxlog_message_handler(u8 phase, const void *message, - size_t length, u32 level, void *data) -{ - struct mxlog *mxlog = (struct mxlog *)data; - - if (!mxlog) { - SCSC_TAG_ERR(MX_FW, "Missing MXLOG reference.\n"); - return; - } - - switch (phase) { - case MX_LOG_PHASE_4: - mxlog_phase4_message_handler(message, length, level, data); - break; - case MX_LOG_PHASE_5: - if (mxlog->logstrings) - mxlog_phase5_message_handler(message, length, - level, data); - else - SCSC_TAG_ERR(MX_FW, - "Missing LogStrings...dropping incoming PHASE5 message !\n"); - break; - default: - SCSC_TAG_ERR(MX_FW, - "MXLOG Unsupported phase %d ... dropping message !\n", - phase); - break; - } -} - -static int mxlog_header_parser(u32 header, u8 *phase, - u8 *level, u32 *num_bytes) -{ - u32 fw2kern_map[] = { - 0, /* 0 MX_ERROR --> 0 KERN_EMERG .. it's panic.*/ - 4, /* 1 MX_WARN --> 4 KERN_WARNING */ - 5, /* 2 MX_MAJOR --> 5 KERN_NOTICE */ - 6, /* 3 MX_MINOR --> 6 KERN_INFO */ - 7, /* 4 MX_DETAIL --> 7 KERN_DEBUG */ - }; - u16 sync = ((header & 0xFFFF0000) >> 16); - - switch (sync) { - case SYNC_VALUE_PHASE_4: - *phase = MX_LOG_PHASE_4; - /* len() field represent number of chars bytes */ - *num_bytes = header & 0x000000FF; - break; - case SYNC_VALUE_PHASE_5: - *phase = MX_LOG_PHASE_5; - /* len() field represent number of 4 bytes words */ - *num_bytes = (header & 0x000000FF) * 4; - break; - default: - return -1; - } - /* Remap FW debug levels to KERN debug levels domain */ - *level = (header & 0x0000FF00) >> 8; - if (*level < ARRAY_SIZE(fw2kern_map)) { - *level = fw2kern_map[*level]; - } else { - SCSC_TAG_ERR(MX_FW, - "UNKNOWN MX debug level %d ... marking as MX_DETAIL.\n", - *level); - *level = fw2kern_map[ARRAY_SIZE(fw2kern_map) - 1]; - } - - return 0; -} - -void mxlog_init(struct mxlog *mxlog, struct scsc_mx *mx, char *fw_build_id) -{ - int ret = 0; - - mxlog->mx = mx; - mxlog->index = 0; - mxlog->logstrings = NULL; - - /* File is in f/w profile directory */ - ret = mx140_file_request_debug_conf(mx, - (const struct firmware **)&mxlog->logstrings, - MX_LOG_LOGSTRINGS_PATH); - - if (!ret && mxlog->logstrings && mxlog->logstrings->data) { - SCSC_TAG_INFO(MX_FW, "Loaded %zd bytes of log-strings from %s\n", - mxlog->logstrings->size, MX_LOG_LOGSTRINGS_PATH); - if (fw_build_id && mxlog->logstrings->data[0] != 0x00 && - mxlog->logstrings->size >= FW_BUILD_ID_SZ) { - SCSC_TAG_INFO(MX_FW, "Log-strings is versioned...checking against fw_build_id.\n"); - if (strncmp(fw_build_id, mxlog->logstrings->data, FW_BUILD_ID_SZ)) { - char found[FW_BUILD_ID_SZ] = {}; - - /** - * NULL-terminate it just in case we fetched - * never-ending garbage. - */ - strncpy(found, mxlog->logstrings->data, - FW_BUILD_ID_SZ - 1); - SCSC_TAG_WARNING(MX_FW, - "--> Log-strings VERSION MISMATCH !!!\n"); - SCSC_TAG_WARNING(MX_FW, - "--> Expected: |%s|\n", fw_build_id); - SCSC_TAG_WARNING(MX_FW, - "--> FOUND: |%s|\n", found); - SCSC_TAG_WARNING(MX_FW, - "As a consequence the following mxlog debug messages could be corrupted.\n"); - SCSC_TAG_WARNING(MX_FW, - "The whole firmware package should be pushed to device when updating (not only the mx140.bin).\n"); - } - } else { - SCSC_TAG_INFO(MX_FW, "Log-strings is not versioned.\n"); - } - } else { - SCSC_TAG_ERR(MX_FW, "Failed to read %s needed by MXlog Phase 5\n", - MX_LOG_LOGSTRINGS_PATH); - } - /* Registering a generic channel handler */ - mxlog_transport_register_channel_handler(scsc_mx_get_mxlog_transport(mx), - &mxlog_header_parser, - &mxlog_message_handler, mxlog); -} - -void mxlog_release(struct mxlog *mxlog) -{ - mxlog_transport_register_channel_handler(scsc_mx_get_mxlog_transport(mxlog->mx), - NULL, NULL, NULL); - if (mxlog->logstrings) - mx140_release_file(mxlog->mx, mxlog->logstrings); - mxlog->logstrings = NULL; -} - diff --git a/drivers/misc/samsung/scsc/mxlog.h b/drivers/misc/samsung/scsc/mxlog.h deleted file mode 100644 index 5b22fed4bdca..000000000000 --- a/drivers/misc/samsung/scsc/mxlog.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef _MXLOG_H -#define _MXLOG_H - -#include - -#define MX_LOG_PHASE_4 4 -#define MX_LOG_PHASE_5 5 - -#define SYNC_VALUE_PHASE_4 (0xA55A) -#define SYNC_VALUE_PHASE_5 (0x9669) - -#define MXLOG_BUFFER_SIZE 512 - -#define MINIMUM_MXLOG_MSG_LEN_BYTES (sizeof(u32) * 2) -#define MXLOG_ELEMENT_SIZE (sizeof(u32)) -#define MAX_SPARE_FMT 256 -#define TSTAMP_LEN 9 -#define MAX_MX_LOG_ARGS 8 -#define MX_LOG_LOGSTRINGS_PATH "common/log-strings.bin" /* in f/w debug dir */ -#define MXLOG_SEXT(x) (((x) & 0x80000000) ? ((x) | 0xffffffff00000000) : (x)) - -#define MXLS_DATA(mx) ((mx)->logstrings->data) -#define MXLS_SZ(mx) ((mx)->logstrings->size) -#define MXLOG_DEFSTR "<<%s OFFSET OUT OF RANGE. Check log-strings.bin>>" -#define MXLOG_STR_SANE(x, base, size, cast) \ - (((x) < (size)) ? (typeof(cast))((base) + (x)) : (typeof(cast))(MXLOG_DEFSTR)) - -#ifdef __aarch64__ -/** - * ARM64 - * ----- - * We must process MXLOG messages 32bit-args coming from FW that have - * a different fmt string interpretation in Kernel: - * - * FW KERN MXLOG_CAST - * --------------------------------------------------------- - * %d s32 s32 (s32) - * %u %x u32 u32 (u32) - * %ld s32 s64 (SIGN_EXT((s64))) - * %lu u32 u64 (u64) - * - * Additionally we take care to skip any %s using defstr, a char pointer, - * as def value for the argument; we casted it to u64 (sizeof(char *)) to fool - * cond expr compilation warnings about types. - */ -#define MXLOG_CAST(x, p, smap, lmap, strmap, base, size) \ - (((strmap) & 1 << (p)) ? MXLOG_STR_SANE(x, base, size, u64) : \ - (((smap) & 1 << (p)) ? \ - (((lmap) & 1 << (p)) ? MXLOG_SEXT((s64)(x)) : (s32)(x)) : \ - (((lmap) & 1 << (p)) ? (u64)(x) : (u32)(x)))) -#else /* __arm__ */ -/** - * ARM32 - * ----- - * We must process MXLOG messages 32bit-args coming from FW BUT in - * ARM 32bit iMX6 they should have the same fmt string interpretation: - * - * FW KERN MXLOG_CAST - * --------------------------------------------------------- - * %d s32 s32 (s32) - * %u %x u32 u32 (u32) - * %ld s32 s32 (s32) - * %lu u32 u32 (u32) - * - * So here we ignore long modifiers and ONLY take care to skip any %s using - * defstr, a char pointer, as def value for the argument; we casted it to - * u32 (sizeof(char *) to fool cond expr compilation warnings about types. - */ -#define MXLOG_CAST(x, p, smap, lmap, strmap, base, size) \ - (((strmap) & 1 << (p)) ? MXLOG_STR_SANE(x, base, size, u32) : \ - (((smap) & 1 << (p)) ? ((s32)(x)) : (u32)(x))) -#endif /* __arch64__ */ - -struct mxlog_event_log_msg { - u32 timestamp; - u32 offset; -} __packed; - -struct mxlog; - -void mxlog_init(struct mxlog *mxlog, struct scsc_mx *mx, char *fw_build_id); -void mxlog_release(struct mxlog *mxlog); - -struct mxlog { - struct scsc_mx *mx; - u8 buffer[MXLOG_BUFFER_SIZE]; - u16 index; - struct firmware *logstrings; -}; - -#endif /* _MXLOG_H */ diff --git a/drivers/misc/samsung/scsc/mxlog_transport.c b/drivers/misc/samsung/scsc/mxlog_transport.c deleted file mode 100644 index ea163b57e76b..000000000000 --- a/drivers/misc/samsung/scsc/mxlog_transport.c +++ /dev/null @@ -1,310 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -/** Uses */ -#include -#include -#include -#include -#include -#include "scsc_mif_abs.h" -#include "mifintrbit.h" -/** Implements */ -#include "mxlog_transport.h" - -#define MXLOG_TRANSPORT_BUF_LENGTH (16 * 1024) -#define MXLOG_TRANSPORT_PACKET_SIZE (4) - -/* Flag that an error has occurred so the I/O thread processing should stop */ -void mxlog_transport_set_error(struct mxlog_transport *mxlog_transport) -{ - SCSC_TAG_WARNING(MXLOG_TRANS, "I/O thread processing is suspended\n"); - - mxlog_transport->mxlog_thread.block_thread = 1; -} - -static void input_irq_handler(int irq, void *data) -{ - struct mxlog_transport *mxlog_transport = (struct mxlog_transport *)data; - struct mxlog_thread *th = &mxlog_transport->mxlog_thread; - struct scsc_mif_abs *mif_abs; - - SCSC_TAG_DEBUG(MXLOG_TRANS, "mxlog intr\n"); - /* Clear the interrupt first to ensure we can't possibly miss one */ - mif_abs = scsc_mx_get_mif_abs(mxlog_transport->mx); - mif_abs->irq_bit_clear(mif_abs, irq); - - /* The the other side wrote some data to the input stream, - * wake up the thread that deals with this. - */ - if (th->task == NULL) { - SCSC_TAG_ERR(MXLOG_TRANS, "mxlog_thread is NOT running\n"); - return; - } - /* - * If an error has occured, we discard silently all messages from - * the stream until the error has been processed and the system has - * been reinitialised. - */ - if (th->block_thread == 1) { - SCSC_TAG_DEBUG(MXLOG_TRANS, "discard message.\n"); - /* - * Do not try to acknowledge a pending interrupt here. - * This function is called by a function which in turn can be - * running in an atomic or 'disabled irq' level. - */ - return; - } - th->wakeup_flag = 1; - - /* wake up I/O thread */ - wake_up_interruptible(&th->wakeup_q); -} - -static void thread_wait_until_stopped(struct mxlog_transport *mxlog_transport) -{ - struct mxlog_thread *th = &mxlog_transport->mxlog_thread; - - /* - * kthread_stop() cannot handle the th exiting while - * kthread_should_stop() is false, so sleep until kthread_stop() - * wakes us up. - */ - SCSC_TAG_INFO(MXLOG_TRANS, "%s waiting for the stop signal.\n", th->name); - set_current_state(TASK_INTERRUPTIBLE); - if (!kthread_should_stop()) { - SCSC_TAG_DEBUG(MXLOG_TRANS, "%s schedule....\n", th->name); - schedule(); - } - - /** - * Caller that spawned the kthread did a get_task_struct() - * on task_struct, that will be released on stop... - * ...so we should NOT nullify th->task here. - */ - SCSC_TAG_DEBUG(MXLOG_TRANS, "%s exiting.\n", th->name); -} - -/** - * A thread that forwards messages sent across the transport to - * the registered handlers for each channel. - */ -static int mxlog_thread_function(void *arg) -{ - struct mxlog_transport *mxlog_transport = (struct mxlog_transport *)arg; - struct mxlog_thread *th = &mxlog_transport->mxlog_thread; - int ret; - u32 header; - char *buf = NULL; - size_t buf_sz = 4096; - - buf = kmalloc(buf_sz, GFP_KERNEL); - if (!buf) { - SCSC_TAG_ERR(MXLOG_TRANS, "Failed to alloc %s local buffer...exiting.\n", th->name); - return -ENOMEM; - } - /* completion is used only for startup thread-synchronization */ - complete(&th->completion); - /* Thread ready...start ISR processing*/ - th->block_thread = 0; - while (!kthread_should_stop()) { - /* wait until an error occurs, or we need to process */ - ret = wait_event_interruptible(th->wakeup_q, - (th->wakeup_flag && !th->block_thread) || - kthread_should_stop()); - - if (kthread_should_stop()) { - SCSC_TAG_DEBUG(MXLOG_TRANS, "signalled to exit\n"); - break; - } - if (ret < 0) { - SCSC_TAG_DEBUG(MXLOG_TRANS, - "wait_event returned %d, thread will exit\n", ret); - thread_wait_until_stopped(mxlog_transport); - break; - } - th->wakeup_flag = 0; - SCSC_TAG_DEBUG(MXLOG_TRANS, "wokeup: r=%d\n", ret); - if (!mxlog_transport->header_handler_fn) { - /* Invalid header handler: - * unrecoverable log and terminate - */ - SCSC_TAG_WARNING(MXLOG_TRANS, - "mxlog_transport->header_handler_fn_==NULL\n"); - break; - } - while (mif_stream_read(&mxlog_transport->mif_stream, - &header, sizeof(uint32_t))) { - u8 level = 0; - u8 phase = 0; - u32 num_bytes = 0; - - mutex_lock(&mxlog_transport->lock); - if (!mxlog_transport->header_handler_fn) { - /* Invalid header handler: - * unrecoverable log and terminate - */ - SCSC_TAG_WARNING(MXLOG_TRANS, - "mxlog_transport->header_handler_fn_==NULL. Channel has been released\n"); - mutex_unlock(&mxlog_transport->lock); - /* not recoverable, terminate straight away */ - goto mxlog_thread_exit; - } - /** - * A generic header processor will properly retrieve - * level and num_bytes as specifically implemented - * by the phase. - */ - if (mxlog_transport->header_handler_fn(header, &phase, - &level, &num_bytes)) { - SCSC_TAG_ERR(MXLOG_TRANS, - "Bad sync in header: header=0x%08x\n", header); - mutex_unlock(&mxlog_transport->lock); - /* not recoverable, terminate straight away */ - goto mxlog_thread_exit; - } - if (num_bytes > 0 && - num_bytes < (MXLOG_TRANSPORT_BUF_LENGTH - sizeof(uint32_t))) { - u32 ret_bytes = 0; - - /* 2nd read - payload (msg) */ - ret_bytes = mif_stream_read(&mxlog_transport->mif_stream, - buf, num_bytes); - mxlog_transport->channel_handler_fn(phase, buf, - ret_bytes, - level, - mxlog_transport->channel_handler_data); - } else { - SCSC_TAG_ERR(MXLOG_TRANS, - "Bad num_bytes(%d) in header: header=0x%08x\n", - num_bytes, header); - } - mutex_unlock(&mxlog_transport->lock); - } - } - -mxlog_thread_exit: - SCSC_TAG_INFO(MXLOG_TRANS, "exiting....\n"); - kfree(buf); - return 0; -} - -static int mxlog_thread_start(struct mxlog_transport *mxlog_transport) -{ - int err; - struct mxlog_thread *th = &mxlog_transport->mxlog_thread; - - if (th->task != NULL) { - SCSC_TAG_WARNING(MXLOG_TRANS, "%s thread already started\n", th->name); - return 0; - } - - /* Initialise thread structure */ - th->block_thread = 1; - init_waitqueue_head(&th->wakeup_q); - init_completion(&th->completion); - th->wakeup_flag = 0; - snprintf(th->name, MXLOG_THREAD_NAME_MAX_LENGTH, "mxlog_thread"); - - /* Start the kernel thread */ - th->task = kthread_run(mxlog_thread_function, mxlog_transport, "%s", th->name); - if (IS_ERR(th->task)) { - int err = (int)PTR_ERR(th->task); - - th->task = NULL; - return err; - } - - /** - * Avoid this task_struct vanishes immediately - * if the kthread exits by its own. - */ - get_task_struct(th->task); - - /* wait until thread function is running */ -#define LOG_THREAD_START_TMO_SEC (3) - err = wait_for_completion_timeout(&th->completion, msecs_to_jiffies(LOG_THREAD_START_TMO_SEC * 1000)); - if (err == 0) { - SCSC_TAG_ERR(MXLOG_TRANS, "timeout starting %s\n", th->name); - kthread_stop(th->task); - put_task_struct(th->task); - return -ETIMEDOUT; - } - SCSC_TAG_INFO(MXLOG_TRANS, "Started thread %s\n", th->name); - - return 0; -} - -static void mxlog_thread_stop(struct mxlog_transport *mxlog_transport) -{ - struct mxlog_thread *th = &mxlog_transport->mxlog_thread; - - if (!th->task) { - SCSC_TAG_WARNING(MXLOG_TRANS, "%s is already stopped\n", th->name); - return; - } - SCSC_TAG_INFO(MXLOG_TRANS, "Stopping thread %s [%d]\n", th->name, th->task->pid); - /* kthread_stop() marks thread as KTHREAD_SHOULD_STOP - * and wait for it to terminate - */ - if (kthread_stop(th->task)) - SCSC_TAG_ERR(MXLOG_TRANS, "Failed to stop %s [%d]\n", th->name, th->task->pid); - /* Finally release the task_struct we held on start */ - put_task_struct(th->task); - th->task = NULL; -} - -void mxlog_transport_release(struct mxlog_transport *mxlog_transport) -{ - mxlog_thread_stop(mxlog_transport); - mif_stream_release(&mxlog_transport->mif_stream); -} - -void mxlog_transport_config_serialise(struct mxlog_transport *mxlog_transport, - struct mxlogconf *mxlogconf) -{ - mif_stream_config_serialise(&mxlog_transport->mif_stream, &mxlogconf->stream_conf); -} - -/** Public functions */ -int mxlog_transport_init(struct mxlog_transport *mxlog_transport, struct scsc_mx *mx) -{ - int r; - uint32_t mem_length = MXLOG_TRANSPORT_BUF_LENGTH; - uint32_t packet_size = MXLOG_TRANSPORT_PACKET_SIZE; - uint32_t num_packets; - - /* - * Initialising a buffer of 1 byte is never legitimate, do not allow it. - * The memory buffer length must be a multiple of the packet size. - */ - - memset(mxlog_transport, 0, sizeof(struct mxlog_transport)); - mutex_init(&mxlog_transport->lock); - num_packets = mem_length / packet_size; - mxlog_transport->mx = mx; - r = mif_stream_init(&mxlog_transport->mif_stream, SCSC_MIF_ABS_TARGET_R4, MIF_STREAM_DIRECTION_IN, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_ALLOC, input_irq_handler, mxlog_transport); - if (r) - return r; - r = mxlog_thread_start(mxlog_transport); - if (r) { - mif_stream_release(&mxlog_transport->mif_stream); - return r; - } - - return 0; -} - -void mxlog_transport_register_channel_handler(struct mxlog_transport *mxlog_transport, - mxlog_header_handler parser, - mxlog_channel_handler handler, - void *data) -{ - mutex_lock(&mxlog_transport->lock); - mxlog_transport->header_handler_fn = parser; - mxlog_transport->channel_handler_fn = handler; - mxlog_transport->channel_handler_data = (void *)data; - mutex_unlock(&mxlog_transport->lock); -} diff --git a/drivers/misc/samsung/scsc/mxlog_transport.h b/drivers/misc/samsung/scsc/mxlog_transport.h deleted file mode 100644 index f82a5ec54541..000000000000 --- a/drivers/misc/samsung/scsc/mxlog_transport.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * Maxwell mxlog transport (Interface) - * - * Provides communication between the firmware and the host. - * - */ - -#ifndef MXLOG_TRANSPORT_H__ -#define MXLOG_TRANSPORT_H__ - -/** Uses */ -#include -#include "mifstream.h" - -struct mxlog_transport; - -typedef int (*mxlog_header_handler)(u32 header, u8 *phase, - u8 *level, u32 *num_bytes); -/** - * Transport channel callback handler. This will be invoked each time a message on a channel is - * received. Handlers may perform work within their callback implementation, but should not block. - * The detected phase is passed as first parameter. - * - * Note that the message pointer passed is only valid for the duration of the function call. - */ -typedef void (*mxlog_channel_handler)(u8 phase, const void *message, - size_t length, u32 level, void *data); - -/** - * Initialises the maxwell management transport and configures the necessary - * interrupt handlers. - */ -int mxlog_transport_init(struct mxlog_transport *mxlog_transport, struct scsc_mx *mx); -void mxlog_transport_release(struct mxlog_transport *mxlog_transport); -/* - * Initialises the configuration area incl. Maxwell Infrastructure Configuration, - * MIF Management Transport Configuration and MIF Management Stream Configuration. - */ -void mxlog_transport_config_serialise(struct mxlog_transport *mxlog_transport, struct mxlogconf *mxlogconf); -void mxlog_transport_register_channel_handler(struct mxlog_transport *mxlog_transport, - mxlog_header_handler parser, - mxlog_channel_handler handler, - void *data); -void mxlog_transport_set_error(struct mxlog_transport *mxlog_transport); - -#define MXLOG_THREAD_NAME_MAX_LENGTH 32 -struct mxlog_thread { - struct task_struct *task; - char name[MXLOG_THREAD_NAME_MAX_LENGTH]; - int prio; - struct completion completion; - wait_queue_head_t wakeup_q; - unsigned int wakeup_flag; - /* - * Use it to block the I/O thread when - * an error occurs. - */ - int block_thread; -}; - -struct mxlog_transport { - struct scsc_mx *mx; - struct mxlog_thread mxlog_thread; - struct mif_stream mif_stream; - mxlog_header_handler header_handler_fn; - mxlog_channel_handler channel_handler_fn; - void *channel_handler_data; - struct mutex lock; -}; - -#endif /* MXLOG_TRANSPORT_H__ */ diff --git a/drivers/misc/samsung/scsc/mxlogger.c b/drivers/misc/samsung/scsc/mxlogger.c deleted file mode 100644 index 80c1d030ad27..000000000000 --- a/drivers/misc/samsung/scsc/mxlogger.c +++ /dev/null @@ -1,945 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** Implements */ -#include "mxlogger.h" - -/** Uses */ -#include -#include -#include -#include -#include -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif - -#include "srvman.h" -#include "scsc_mif_abs.h" -#include "miframman.h" -#include "mifintrbit.h" -#include "mxmgmt_transport.h" - -static bool mxlogger_disabled; -module_param(mxlogger_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mxlogger_disabled, "Disable MXLOGGER Configuration. Effective only at next WLBT boot."); - -bool mxlogger_set_enabled_status(bool enable) -{ - mxlogger_disabled = !enable; - - SCSC_TAG_INFO(MXMAN, "MXLOGGER has been NOW %sABLED. Effective at next WLBT boot.\n", - mxlogger_disabled ? "DIS" : "EN"); - - return mxlogger_disabled; -} -EXPORT_SYMBOL(mxlogger_set_enabled_status); - -static bool mxlogger_forced_to_host; - -static void update_fake_observer(void) -{ - static bool mxlogger_fake_observers_registered; - - if (mxlogger_forced_to_host) { - if (!mxlogger_fake_observers_registered) { - mxlogger_register_global_observer("FAKE_OBSERVER"); - mxlogger_fake_observers_registered = true; - } - SCSC_TAG_INFO(MXMAN, "MXLOGGER is now FORCED TO HOST.\n"); - } else { - if (mxlogger_fake_observers_registered) { - mxlogger_unregister_global_observer("FAKE_OBSERVER"); - mxlogger_fake_observers_registered = false; - } - SCSC_TAG_INFO(MXMAN, "MXLOGGER is now operating NORMALLY.\n"); - } -} - -static int mxlogger_force_to_host_set_param_cb(const char *val, - const struct kernel_param *kp) -{ - bool nval; - - if (!val || strtobool(val, &nval)) - return -EINVAL; - - if (mxlogger_forced_to_host ^ nval) { - mxlogger_forced_to_host = nval; - update_fake_observer(); - } - return 0; -} - -/** - * As described in struct kernel_param+ops the _get method: - * -> returns length written or -errno. Buffer is 4k (ie. be short!) - */ -static int mxlogger_force_to_host_get_param_cb(char *buffer, - const struct kernel_param *kp) -{ - return sprintf(buffer, "%c", mxlogger_forced_to_host ? 'Y' : 'N'); -} - -static struct kernel_param_ops mxlogger_force_to_host_ops = { - .set = mxlogger_force_to_host_set_param_cb, - .get = mxlogger_force_to_host_get_param_cb, -}; -module_param_cb(mxlogger_force_to_host, &mxlogger_force_to_host_ops, NULL, 0644); -MODULE_PARM_DESC(mxlogger_force_to_host, "Force mxlogger to redirect to Host all the time, using a fake observer."); - -/** - * Observers of log material could come and go before mxman and mxlogger - * are initialized and started...so we keep this stuff here out of mxman, - * but all the lifecycle of mxlogger should be reviewed. - */ -static u8 active_global_observers; -static DEFINE_MUTEX(global_lock); - -struct mxlogger_node { - struct list_head list; - struct mxlogger *mxl; -}; -static struct mxlogger_list { struct list_head list; } mxlogger_list = { - .list = LIST_HEAD_INIT(mxlogger_list.list) -}; - -#ifdef CONFIG_SCSC_LOG_COLLECTION -static int mxlogger_collect_init(struct scsc_log_collector_client *collect_client); -static int mxlogger_collect(struct scsc_log_collector_client *collect_client, size_t size); -static int mxlogger_collect_end(struct scsc_log_collector_client *collect_client); - -/* Collect client registration SYNC buffer */ -/* SYNC - SHOULD BE THE FIRST CHUNK TO BE CALLED - SO USE THE INIT/END ON THIS CLIENT */ -struct scsc_log_collector_client mxlogger_collect_client_sync = { - .name = "Sync", - .type = SCSC_LOG_CHUNK_SYNC, - .collect_init = mxlogger_collect_init, - .collect = mxlogger_collect, - .collect_end = mxlogger_collect_end, - .prv = NULL, -}; - -/* Collect client registration IMP buffer */ -struct scsc_log_collector_client mxlogger_collect_client_imp = { - .name = "Important", - .type = SCSC_LOG_CHUNK_IMP, - .collect_init = NULL, - .collect = mxlogger_collect, - .collect_end = NULL, - .prv = NULL, -}; - -struct scsc_log_collector_client mxlogger_collect_client_rsv_common = { - .name = "Rsv_common", - .type = SCSC_LOG_RESERVED_COMMON, - .collect_init = NULL, - .collect = mxlogger_collect, - .collect_end = NULL, - .prv = NULL, -}; - -struct scsc_log_collector_client mxlogger_collect_client_rsv_bt = { - .name = "Rsv_bt", - .type = SCSC_LOG_RESERVED_BT, - .collect_init = NULL, - .collect = mxlogger_collect, - .collect_end = NULL, - .prv = NULL, -}; - -struct scsc_log_collector_client mxlogger_collect_client_rsv_wlan = { - .name = "Rsv_wlan", - .type = SCSC_LOG_RESERVED_WLAN, - .collect_init = NULL, - .collect = mxlogger_collect, - .collect_end = NULL, - .prv = NULL, -}; - -struct scsc_log_collector_client mxlogger_collect_client_rsv_radio = { - .name = "Rsv_radio", - .type = SCSC_LOG_RESERVED_RADIO, - .collect_init = NULL, - .collect = mxlogger_collect, - .collect_end = NULL, - .prv = NULL, -}; -/* Collect client registration MXL buffer */ -struct scsc_log_collector_client mxlogger_collect_client_mxl = { - .name = "MXL", - .type = SCSC_LOG_CHUNK_MXL, - .collect_init = NULL, - .collect = mxlogger_collect, - .collect_end = NULL, - .prv = NULL, -}; - -/* Collect client registration MXL buffer */ -struct scsc_log_collector_client mxlogger_collect_client_udi = { - .name = "UDI", - .type = SCSC_LOG_CHUNK_UDI, - .collect_init = NULL, - .collect = mxlogger_collect, - .collect_end = NULL, - .prv = NULL, -}; -#endif - -const char *mxlogger_buf_name[] = { "syn", "imp", "rsv_common", "rsv_bt", "rsv_wlan", "rsv_radio", "mxl", "udi" }; - -static void mxlogger_message_handler(const void *message, void *data) -{ - struct mxlogger __attribute__((unused)) *mxlogger = (struct mxlogger *)data; - const struct log_msg_packet *msg = message; - u16 reason_code; - - switch (msg->msg) { - case MM_MXLOGGER_INITIALIZED_EVT: - SCSC_TAG_INFO(MXMAN, "MXLOGGER Initialized.\n"); - mxlogger->initialized = true; - complete(&mxlogger->rings_serialized_ops); - break; - case MM_MXLOGGER_STARTED_EVT: - SCSC_TAG_INFO(MXMAN, "MXLOGGER:: RINGS Enabled.\n"); - mxlogger->enabled = true; - complete(&mxlogger->rings_serialized_ops); - break; - case MM_MXLOGGER_STOPPED_EVT: - SCSC_TAG_INFO(MXMAN, "MXLOGGER:: RINGS Disabled.\n"); - mxlogger->enabled = false; - complete(&mxlogger->rings_serialized_ops); - break; - case MM_MXLOGGER_COLLECTION_FW_REQ_EVT: - /* If arg is zero, FW is using the 16bit reason code API */ - /* therefore, the reason code is in the payload */ - if (msg->arg == 0x00) - memcpy(&reason_code, &msg->payload[0], sizeof(u16)); - else - /* old API */ - reason_code = msg->arg; -#ifdef CONFIG_SCSC_LOG_COLLECTION - SCSC_TAG_INFO(MXMAN, "MXLOGGER:: FW requested collection - Reason code:0x%04x\n", reason_code); - scsc_log_collector_schedule_collection(SCSC_LOG_FW, reason_code); -#endif - break; - default: - SCSC_TAG_WARNING(MXMAN, - "Received UNKNOWN msg on MMTRANS_CHAN_ID_MAXWELL_LOGGING -- msg->msg=%d\n", - msg->msg); - break; - } -} - -static int __mxlogger_generate_sync_record(struct mxlogger *mxlogger, enum mxlogger_sync_event event) -{ - struct mxlogger_sync_record *sync_r_mem; - struct timeval t; - struct log_msg_packet msg = {}; - unsigned long int jd; - void *mem; - ktime_t t1, t2; - - /* Assume mxlogger->lock mutex is held */ - if (!mxlogger || !mxlogger->configured) - return -EIO; - - msg.msg = MM_MXLOGGER_SYNC_RECORD; - msg.arg = MM_MXLOGGER_SYNC_INDEX; - memcpy(&msg.payload, &mxlogger->sync_buffer_index, sizeof(mxlogger->sync_buffer_index)); - - /* Get the pointer from the index of the sync array */ - mem = mxlogger->mem_sync_buf + mxlogger->sync_buffer_index * sizeof(struct mxlogger_sync_record); - sync_r_mem = (struct mxlogger_sync_record *)mem; - /* Write values in record as FW migth be doing sanity checks */ - sync_r_mem->tv_sec = 1; - sync_r_mem->tv_usec = 1; - sync_r_mem->kernel_time = 1; - sync_r_mem->sync_event = event; - sync_r_mem->fw_time = 0; - sync_r_mem->fw_wrap = 0; - - - SCSC_TAG_INFO(MXMAN, "Get FW time\n"); - preempt_disable(); - /* set the tight loop timeout - we do not require precission but something to not - * loop forever - */ - jd = jiffies + msecs_to_jiffies(20); - /* Send the msg as fast as possible */ - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxlogger->mx), - MMTRANS_CHAN_ID_MAXWELL_LOGGING, - &msg, sizeof(msg)); - t1 = ktime_get(); - /* Tight loop to read memory */ - while (time_before(jiffies, jd) && sync_r_mem->fw_time == 0 && sync_r_mem->fw_wrap == 0) - ; - t2 = ktime_get(); - do_gettimeofday(&t); - preempt_enable(); - - /* Do the processing */ - if (sync_r_mem->fw_wrap == 0 && sync_r_mem->fw_time == 0) { - /* FW didn't update the record (FW panic?) */ - SCSC_TAG_INFO(MXMAN, "FW failure updating the FW time\n"); - SCSC_TAG_INFO(MXMAN, "Sync delta %lld\n", ktime_to_ns(ktime_sub(t2, t1))); - sync_r_mem->tv_sec = (u64)t.tv_sec; - sync_r_mem->tv_usec = (u64)t.tv_usec; - sync_r_mem->kernel_time = ktime_to_ns(t2); - sync_r_mem->sync_event = event; - return 0; - } - - sync_r_mem->tv_sec = (u64)t.tv_sec; - sync_r_mem->tv_usec = (u64)t.tv_usec; - sync_r_mem->kernel_time = ktime_to_ns(t2); - sync_r_mem->sync_event = event; - - SCSC_TAG_INFO(MXMAN, "Sample, %lld, %u, %lld.%06lld\n", - ktime_to_ns(sync_r_mem->kernel_time), sync_r_mem->fw_time, sync_r_mem->tv_sec, sync_r_mem->tv_usec); - SCSC_TAG_INFO(MXMAN, "Sync delta %lld\n", ktime_to_ns(ktime_sub(t2, t1))); - - mxlogger->sync_buffer_index++; - mxlogger->sync_buffer_index &= SYNC_MASK; - - return 0; -} - -int mxlogger_generate_sync_record(struct mxlogger *mxlogger, enum mxlogger_sync_event event) -{ - int r; - - mutex_lock(&mxlogger->lock); - r = __mxlogger_generate_sync_record(mxlogger, event); - mutex_unlock(&mxlogger->lock); - - return r; -} - -static void mxlogger_wait_for_msg_reinit_completion(struct mxlogger *mxlogger) -{ - reinit_completion(&mxlogger->rings_serialized_ops); -} - -static bool mxlogger_wait_for_msg_reply(struct mxlogger *mxlogger) -{ - int ret; - - ret = wait_for_completion_timeout(&mxlogger->rings_serialized_ops, usecs_to_jiffies(MXLOGGER_RINGS_TMO_US)); - if (ret) { - int i; - - SCSC_TAG_DBG3(MXMAN, "MXLOGGER RINGS -- replied in %lu usecs.\n", - MXLOGGER_RINGS_TMO_US - jiffies_to_usecs(ret)); - - for (i = 0; i < MXLOGGER_NUM_BUFFERS; i++) - SCSC_TAG_DBG3(MXMAN, "MXLOGGER:: RING[%d] -- INFO[0x%X] STATUS[0x%X]\n", i, - mxlogger->cfg->bfds[i].info, mxlogger->cfg->bfds[i].status); - } else { - SCSC_TAG_ERR(MXMAN, "MXLOGGER timeout waiting for reply.\n"); - } - - return ret ? true : false; -} - -static inline void __mxlogger_enable(struct mxlogger *mxlogger, bool enable, uint8_t reason) -{ - struct log_msg_packet msg = {}; - - msg.msg = MM_MXLOGGER_LOGGER_CMD; - msg.arg = (enable) ? MM_MXLOGGER_LOGGER_ENABLE : MM_MXLOGGER_LOGGER_DISABLE; - msg.payload[0] = reason; - - /* Reinit the completion before sending the message over cpacketbuffer - * otherwise there might be a race condition - */ - mxlogger_wait_for_msg_reinit_completion(mxlogger); - - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxlogger->mx), - MMTRANS_CHAN_ID_MAXWELL_LOGGING, - &msg, sizeof(msg)); - - SCSC_TAG_DBG4(MXMAN, "MXLOGGER RINGS -- enable:%d reason:%d\n", - enable, reason); - - mxlogger_wait_for_msg_reply(mxlogger); -} - -static void mxlogger_enable(struct mxlogger *mxlogger, bool enable) -{ - return __mxlogger_enable(mxlogger, enable, MM_MXLOGGER_DISABLE_REASON_STOP); -} - -static int mxlogger_send_config(struct mxlogger *mxlogger) -{ - struct log_msg_packet msg = {}; - - SCSC_TAG_INFO(MXMAN, "MXLOGGER Config mifram_ref: 0x%x size:%d\n", - mxlogger->mifram_ref, mxlogger->msz); - - msg.msg = MM_MXLOGGER_CONFIG_CMD; - msg.arg = MM_MXLOGGER_CONFIG_BASE_ADDR; - memcpy(&msg.payload, &mxlogger->mifram_ref, sizeof(mxlogger->mifram_ref)); - - /* Reinit the completion before sending the message over cpacketbuffer - * otherwise there might be a race condition - */ - mxlogger_wait_for_msg_reinit_completion(mxlogger); - - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxlogger->mx), - MMTRANS_CHAN_ID_MAXWELL_LOGGING, - &msg, sizeof(msg)); - - SCSC_TAG_INFO(MXMAN, "MXLOGGER Config SENT\n"); - if (!mxlogger_wait_for_msg_reply(mxlogger)) - return -1; - - return 0; -} - -static void mxlogger_to_shared_dram(struct mxlogger *mxlogger) -{ - int r; - struct log_msg_packet msg = { .msg = MM_MXLOGGER_DIRECTION_CMD, - .arg = MM_MXLOGGER_DIRECTION_DRAM }; - - SCSC_TAG_INFO(MXMAN, "MXLOGGER -- NO active observers detected. Send logs to DRAM\n"); - - r = __mxlogger_generate_sync_record(mxlogger, MXLOGGER_SYN_TORAM); - if (r) - return; /* mxlogger is not configured */ - - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxlogger->mx), - MMTRANS_CHAN_ID_MAXWELL_LOGGING, - &msg, sizeof(msg)); -} - -static void mxlogger_to_host(struct mxlogger *mxlogger) -{ - int r; - struct log_msg_packet msg = { .msg = MM_MXLOGGER_DIRECTION_CMD, - .arg = MM_MXLOGGER_DIRECTION_HOST }; - - SCSC_TAG_INFO(MXMAN, "MXLOGGER -- active observers detected. Send logs to host\n"); - - r = __mxlogger_generate_sync_record(mxlogger, MXLOGGER_SYN_TOHOST); - if (r) - return; /* mxlogger is not configured */ - - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxlogger->mx), - MMTRANS_CHAN_ID_MAXWELL_LOGGING, - &msg, sizeof(msg)); -} - -#ifdef CONFIG_SCSC_LOG_COLLECTION -static void mxlogger_disable_for_collection(struct mxlogger *mxlogger) -{ - return __mxlogger_enable(mxlogger, false, MM_MXLOGGER_DISABLE_REASON_COLLECTION); -} - -static int mxlogger_collect_init(struct scsc_log_collector_client *collect_client) -{ - struct mxlogger *mxlogger = (struct mxlogger *)collect_client->prv; - - if (!mxlogger->initialized) - return 0; - - mutex_lock(&mxlogger->lock); - - SCSC_TAG_INFO(MXMAN, "Started log collection\n"); - - __mxlogger_generate_sync_record(mxlogger, MXLOGGER_SYN_LOGCOLLECTION); - - mxlogger->re_enable = mxlogger->enabled; - /** - * If enabled, tell FW we are stopping for collection: - * this way FW can dump last minute stuff and flush properly - * its cache - */ - if (mxlogger->enabled) - mxlogger_disable_for_collection(mxlogger); - - mutex_unlock(&mxlogger->lock); - - return 0; -} - -static int mxlogger_collect(struct scsc_log_collector_client *collect_client, size_t size) -{ - struct scsc_mif_abs *mif; - struct mxlogger *mxlogger = (struct mxlogger *)collect_client->prv; - void *buf; - int ret = 0; - int i; - size_t sz; - - if (mxlogger && mxlogger->mx) - mif = scsc_mx_get_mif_abs(mxlogger->mx); - else - /* Return 0 as 'success' to continue the collection of other chunks */ - return 0; - - mutex_lock(&mxlogger->lock); - - if (mxlogger->initialized == false) { - SCSC_TAG_ERR(MXMAN, "MXLOGGER not initialized\n"); - mutex_unlock(&mxlogger->lock); - return 0; - } - - if (collect_client->type == SCSC_LOG_CHUNK_SYNC) - i = MXLOGGER_SYNC; - else if (collect_client->type == SCSC_LOG_CHUNK_IMP) - i = MXLOGGER_IMP; - else if (collect_client->type == SCSC_LOG_RESERVED_COMMON) - i = MXLOGGER_RESERVED_COMMON; - else if (collect_client->type == SCSC_LOG_RESERVED_BT) - i = MXLOGGER_RESERVED_BT; - else if (collect_client->type == SCSC_LOG_RESERVED_WLAN) - i = MXLOGGER_RESERVED_WLAN; - else if (collect_client->type == SCSC_LOG_RESERVED_RADIO) - i = MXLOGGER_RESERVED_RADIO; - else if (collect_client->type == SCSC_LOG_CHUNK_MXL) - i = MXLOGGER_MXLOG; - else if (collect_client->type == SCSC_LOG_CHUNK_UDI) - i = MXLOGGER_UDI; - else { - SCSC_TAG_ERR(MXMAN, "MXLOGGER Incorrect type. Return 'success' and continue to collect other buffers\n"); - mutex_unlock(&mxlogger->lock); - return 0; - } - - sz = mxlogger->cfg->bfds[i].size; - buf = mif->get_mifram_ptr(mif, mxlogger->cfg->bfds[i].location); - SCSC_TAG_INFO(MXMAN, "Writing buffer %s size: %zu\n", mxlogger_buf_name[i], sz); - ret = scsc_log_collector_write(buf, sz, 1); - if (ret) { - mutex_unlock(&mxlogger->lock); - return ret; - } - - mutex_unlock(&mxlogger->lock); - return 0; -} - -static int mxlogger_collect_end(struct scsc_log_collector_client *collect_client) -{ - struct mxlogger *mxlogger = (struct mxlogger *)collect_client->prv; - - if (!mxlogger->initialized) - return 0; - - mutex_lock(&mxlogger->lock); - - SCSC_TAG_INFO(MXMAN, "End log collection\n"); - - /* Renable again if was previoulsy enabled */ - if (mxlogger->re_enable) - mxlogger_enable(mxlogger, true); - - mutex_unlock(&mxlogger->lock); - return 0; -} -#endif - -void mxlogger_print_mapping(struct mxlogger_config_area *cfg) -{ - u8 i; - - SCSC_TAG_INFO(MXMAN, "MXLOGGER -- Configured Buffers [%d]\n", cfg->config.num_buffers); - for (i = 0; i < MXLOGGER_NUM_BUFFERS; i++) - SCSC_TAG_INFO(MXMAN, "buffer %s loc: 0x%08x size: %u\n", - mxlogger_buf_name[i], cfg->bfds[i].location, cfg->bfds[i].size); - -} - -/* Lock should be acquired by caller */ -int mxlogger_init(struct scsc_mx *mx, struct mxlogger *mxlogger, uint32_t mem_sz) -{ - struct miframman *miframman; - struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(mx); - struct mxlogger_config_area *cfg; - size_t remaining_mem; - size_t udi_mxl_mem_sz; - struct mxlogger_node *mn; - - MEM_LAYOUT_CHECK(); - - mxlogger->configured = false; - - if (mem_sz <= (sizeof(struct mxlogger_config_area) + MXLOGGER_TOTAL_FIX_BUF)) { - SCSC_TAG_ERR(MXMAN, "Insufficient memory allocation\n"); - return -EIO; - } - - mxlogger->mx = mx; - miframman = scsc_mx_get_ramman2(mx); - if (!miframman) - return -ENOMEM; - mxlogger->mem = miframman_alloc(miframman, mem_sz, 32, MIFRAMMAN_OWNER_COMMON); - if (!mxlogger->mem) { - SCSC_TAG_ERR(MXMAN, "Error allocating memory for MXLOGGER\n"); - return -ENOMEM; - } - mxlogger->msz = mem_sz; - - /* Clear memory to avoid reading old records */ - memset(mxlogger->mem, 0, mxlogger->msz); - mif->get_mifram_ref(mif, mxlogger->mem, &mxlogger->mifram_ref); - - mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mxlogger->mx), - MMTRANS_CHAN_ID_MAXWELL_LOGGING, - &mxlogger_message_handler, mxlogger); - - /* Initialize configuration structure */ - SCSC_TAG_INFO(MXMAN, "MXLOGGER Configuration: 0x%x\n", (u32)mxlogger->mifram_ref); - cfg = (struct mxlogger_config_area *)mxlogger->mem; - - cfg->config.magic_number = MXLOGGER_MAGIG_NUMBER; - cfg->config.config_major = MXLOGGER_MAJOR; - cfg->config.config_minor = MXLOGGER_MINOR; - cfg->config.num_buffers = MXLOGGER_NUM_BUFFERS; - - /** - * Populate information of Fixed size buffers - * These are mifram-reletive references - */ - cfg->bfds[MXLOGGER_SYNC].location = mxlogger->mifram_ref + - offsetof(struct mxlogger_config_area, buffers_start); - cfg->bfds[MXLOGGER_SYNC].size = MXLOGGER_SYNC_SIZE; - /* additionally cache the va of sync_buffer */ - mxlogger->mem_sync_buf = mxlogger->mem + - offsetof(struct mxlogger_config_area, buffers_start); - - cfg->bfds[MXLOGGER_IMP].location = - cfg->bfds[MXLOGGER_IMP - 1].location + - cfg->bfds[MXLOGGER_IMP - 1].size; - cfg->bfds[MXLOGGER_IMP].size = MXLOGGER_IMP_SIZE; - - cfg->bfds[MXLOGGER_RESERVED_COMMON].location = - cfg->bfds[MXLOGGER_RESERVED_COMMON - 1].location + - cfg->bfds[MXLOGGER_RESERVED_COMMON - 1].size; - cfg->bfds[MXLOGGER_RESERVED_COMMON].size = MXLOGGER_RSV_COMMON_SZ; - - cfg->bfds[MXLOGGER_RESERVED_BT].location = - cfg->bfds[MXLOGGER_RESERVED_BT - 1].location + - cfg->bfds[MXLOGGER_RESERVED_BT - 1].size; - cfg->bfds[MXLOGGER_RESERVED_BT].size = MXLOGGER_RSV_BT_SZ; - - cfg->bfds[MXLOGGER_RESERVED_WLAN].location = - cfg->bfds[MXLOGGER_RESERVED_WLAN - 1].location + - cfg->bfds[MXLOGGER_RESERVED_WLAN - 1].size; - cfg->bfds[MXLOGGER_RESERVED_WLAN].size = MXLOGGER_RSV_WLAN_SZ; - - cfg->bfds[MXLOGGER_RESERVED_RADIO].location = - cfg->bfds[MXLOGGER_RESERVED_RADIO - 1].location + - cfg->bfds[MXLOGGER_RESERVED_RADIO - 1].size; - cfg->bfds[MXLOGGER_RESERVED_RADIO].size = MXLOGGER_RSV_RADIO_SZ; - - /* Compute buffer locations and size based on the remaining space */ - remaining_mem = mem_sz - (sizeof(struct mxlogger_config_area) + MXLOGGER_TOTAL_FIX_BUF); - - /* Align the buffer to be cache friendly */ - udi_mxl_mem_sz = (remaining_mem >> 1) & ~(MXLOGGER_NON_FIX_BUF_ALIGN - 1); - - SCSC_TAG_INFO(MXMAN, "remaining_mem %zu udi/mxlogger size %zu\n", remaining_mem, udi_mxl_mem_sz); - - cfg->bfds[MXLOGGER_MXLOG].location = - cfg->bfds[MXLOGGER_MXLOG - 1].location + - cfg->bfds[MXLOGGER_MXLOG - 1].size; - cfg->bfds[MXLOGGER_MXLOG].size = udi_mxl_mem_sz; - - cfg->bfds[MXLOGGER_UDI].location = - cfg->bfds[MXLOGGER_UDI - 1].location + - cfg->bfds[MXLOGGER_UDI - 1].size; - cfg->bfds[MXLOGGER_UDI].size = udi_mxl_mem_sz; - - /* Save offset to buffers array */ - mif->get_mifram_ref(mif, cfg->bfds, &cfg->config.bfds_ref); - - mxlogger_print_mapping(cfg); - - mxlogger->cfg = cfg; - - init_completion(&mxlogger->rings_serialized_ops); - mxlogger->enabled = false; - - mutex_init(&mxlogger->lock); - - mn = kzalloc(sizeof(*mn), GFP_KERNEL); - if (!mn) { - miframman_free(miframman, mxlogger->mem); - return -ENOMEM; - } - - /** - * Update observers status considering - * current value of mxlogger_forced_to_host - */ - update_fake_observer(); - - mutex_lock(&global_lock); - mxlogger->observers = active_global_observers; - if (mxlogger->observers) - SCSC_TAG_INFO(MXMAN, "Detected global %d observer[s]\n", active_global_observers); - mutex_unlock(&global_lock); - - mxlogger->sync_buffer_index = 0; - - mn->mxl = mxlogger; - list_add_tail(&mn->list, &mxlogger_list.list); - -#ifdef CONFIG_SCSC_LOG_COLLECTION - /** - * Register to the collection infrastructure - * - * All of mxlogger buffers are registered here, NO matter if - * MXLOGGER initialization was successfull FW side. - * - * In such a case MXLOGGER-FW will simply ignore all of our following - * requests and we'll end up dumping empty buffers, BUT with a partially - * meaningful sync buffer. (since this last is written also Host side) - */ - mxlogger_collect_client_sync.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_sync); - - mxlogger_collect_client_imp.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_imp); - - mxlogger_collect_client_rsv_common.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_rsv_common); - - mxlogger_collect_client_rsv_bt.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_rsv_bt); - - mxlogger_collect_client_rsv_wlan.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_rsv_wlan); - - mxlogger_collect_client_rsv_radio.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_rsv_radio); - - mxlogger_collect_client_udi.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_udi); - - mxlogger_collect_client_mxl.prv = mxlogger; - scsc_log_collector_register_client(&mxlogger_collect_client_mxl); -#endif - mxlogger->configured = true; - SCSC_TAG_INFO(MXMAN, "MXLOGGER Configured\n"); - return 0; -} - -int mxlogger_start(struct mxlogger *mxlogger) -{ - if (mxlogger_disabled) { - SCSC_TAG_WARNING(MXMAN, "MXLOGGER is disabled. Not Starting.\n"); - return -1; - } - - if (!mxlogger || !mxlogger->configured) { - SCSC_TAG_WARNING(MXMAN, "MXLOGGER is not valid or not configured.\n"); - return -1; - } - - SCSC_TAG_INFO(MXMAN, "Starting mxlogger with %d observer[s]\n", mxlogger->observers); - - mutex_lock(&mxlogger->lock); - if (mxlogger_send_config(mxlogger)) { - mutex_unlock(&mxlogger->lock); - return -ENOMEM; - } - - /** - * MXLOGGER on FW-side is at this point starting up too during - * WLBT chip boot and it cannot make any assumption till about - * the current number of observers and direction set: so, during - * MXLOGGER FW-side initialization, ZERO observers were registered. - * - * As a consequence on chip-boot FW-MXLOGGER defaults to: - * - direction DRAM - * - all rings disabled (ingressing messages discarded) - */ - if (!mxlogger->observers) { - /* Enabling BEFORE communicating direction DRAM - * to avoid losing messages on rings. - */ - mxlogger_enable(mxlogger, true); - mxlogger_to_shared_dram(mxlogger); -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_is_observer(false); -#endif - } else { - mxlogger_to_host(mxlogger); -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_is_observer(true); -#endif - /* Enabling AFTER communicating direction HOST - * to avoid wrongly spilling messages into the - * rings early at start (like at boot). - */ - mxlogger_enable(mxlogger, true); - } - - SCSC_TAG_INFO(MXMAN, "MXLOGGER Started.\n"); - mutex_unlock(&mxlogger->lock); - - return 0; -} - -void mxlogger_deinit(struct scsc_mx *mx, struct mxlogger *mxlogger) -{ - struct miframman *miframman = NULL; - struct mxlogger_node *mn, *next; - bool match = false; - - SCSC_TAG_INFO(MXMAN, "\n"); - - if (!mxlogger || !mxlogger->configured) { - SCSC_TAG_WARNING(MXMAN, "MXLOGGER is not valid or not configured.\n"); - return; - } - /* Run deregistration before adquiring the mxlogger lock to avoid - * deadlock with log_collector. - */ -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_unregister_client(&mxlogger_collect_client_sync); - scsc_log_collector_unregister_client(&mxlogger_collect_client_imp); - scsc_log_collector_unregister_client(&mxlogger_collect_client_rsv_common); - scsc_log_collector_unregister_client(&mxlogger_collect_client_rsv_bt); - scsc_log_collector_unregister_client(&mxlogger_collect_client_rsv_wlan); - scsc_log_collector_unregister_client(&mxlogger_collect_client_rsv_radio); - scsc_log_collector_unregister_client(&mxlogger_collect_client_mxl); - scsc_log_collector_unregister_client(&mxlogger_collect_client_udi); -#endif - mutex_lock(&mxlogger->lock); - - mxlogger_to_host(mxlogger); /* immediately before deconfigure to get a last sync rec */ - mxlogger->configured = false; - mxlogger->initialized = false; - -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_is_observer(true); -#endif - mxlogger_enable(mxlogger, false); - mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mxlogger->mx), - MMTRANS_CHAN_ID_MAXWELL_LOGGING, - NULL, NULL); - miframman = scsc_mx_get_ramman2(mx); - if (miframman) - miframman_free(miframman, mxlogger->mem); - - list_for_each_entry_safe(mn, next, &mxlogger_list.list, list) { - if (mn->mxl == mxlogger) { - match = true; - list_del(&mn->list); - kfree(mn); - } - } - - if (match == false) - SCSC_TAG_ERR(MXMAN, "FATAL, no match for given scsc_mif_abs\n"); - - SCSC_TAG_INFO(MXMAN, "End\n"); - mutex_unlock(&mxlogger->lock); -} - -int mxlogger_register_observer(struct mxlogger *mxlogger, char *name) -{ - mutex_lock(&mxlogger->lock); - - mxlogger->observers++; - - SCSC_TAG_INFO(MXMAN, "Register observer[%d] -- %s\n", - mxlogger->observers, name); - - /* Switch logs to host */ - mxlogger_to_host(mxlogger); -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_is_observer(true); -#endif - - mutex_unlock(&mxlogger->lock); - - return 0; -} - -int mxlogger_unregister_observer(struct mxlogger *mxlogger, char *name) -{ - mutex_lock(&mxlogger->lock); - - if (mxlogger->observers == 0) { - SCSC_TAG_INFO(MXMAN, "Incorrect number of observers\n"); - mutex_unlock(&mxlogger->lock); - return -EIO; - } - - mxlogger->observers--; - - SCSC_TAG_INFO(MXMAN, "UN-register observer[%d] -- %s\n", - mxlogger->observers, name); - - if (mxlogger->observers == 0) { - mxlogger_to_shared_dram(mxlogger); -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_is_observer(false); -#endif - } - - mutex_unlock(&mxlogger->lock); - - return 0; -} - -/* Global observer are not associated to any [mx] mxlogger instance. So it registers as - * an observer to all the [mx] mxlogger instances. - */ -int mxlogger_register_global_observer(char *name) -{ - struct mxlogger_node *mn, *next; - - mutex_lock(&global_lock); - active_global_observers++; - - SCSC_TAG_INFO(MXMAN, "Register global observer[%d] -- %s\n", - active_global_observers, name); - - if (list_empty(&mxlogger_list.list)) { - SCSC_TAG_INFO(MXMAN, "No instances of mxman\n"); - mutex_unlock(&global_lock); - return -EIO; - } - - list_for_each_entry_safe(mn, next, &mxlogger_list.list, list) { - /* There is a mxlogger instance */ - mxlogger_register_observer(mn->mxl, name); - } - - mutex_unlock(&global_lock); - - return 0; -} - -int mxlogger_unregister_global_observer(char *name) -{ - struct mxlogger_node *mn, *next; - - mutex_lock(&global_lock); - if (active_global_observers) - active_global_observers--; - - SCSC_TAG_INFO(MXMAN, "UN-register global observer[%d] -- %s\n", - active_global_observers, name); - - list_for_each_entry_safe(mn, next, &mxlogger_list.list, list) { - /* There is a mxlogger instance */ - mxlogger_unregister_observer(mn->mxl, name); - } - - mutex_unlock(&global_lock); - - return 0; -} - diff --git a/drivers/misc/samsung/scsc/mxlogger.h b/drivers/misc/samsung/scsc/mxlogger.h deleted file mode 100644 index ad80abd7c3b5..000000000000 --- a/drivers/misc/samsung/scsc/mxlogger.h +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * Maxwell mxlogger (Interface) - * - * Provides bi-directional communication between the firmware and the - * host. - * - */ - -#ifndef __MX_LOGGER_H__ -#define __MX_LOGGER_H__ - -#include -#include -#include -#include -#include -#include -#include - -#include "mxmgmt_transport_format.h" - -/** - * ___________________________________________________________________ - * | Cmd | Arg | ... payload (opt) ... | - * ------------------------------------------------------------------- - * <-- uint8_t --><-- uint8_t --><----- uint8_t[] buffer -----------> - * - */ - -#define MXL_POOL_SZ (6 * 1024 * 1024) - -#define MXLOGGER_RINGS_TMO_US 200000 - -/* CMD/EVENTS */ -#define MM_MXLOGGER_LOGGER_CMD (0) -#define MM_MXLOGGER_DIRECTION_CMD (1) -#define MM_MXLOGGER_CONFIG_CMD (2) -#define MM_MXLOGGER_INITIALIZED_EVT (3) -#define MM_MXLOGGER_SYNC_RECORD (4) -#define MM_MXLOGGER_STARTED_EVT (5) -#define MM_MXLOGGER_STOPPED_EVT (6) -#define MM_MXLOGGER_COLLECTION_FW_REQ_EVT (7) - -/* ARG - LOGGER */ -#define MM_MXLOGGER_LOGGER_ENABLE (0) -#define MM_MXLOGGER_LOGGER_DISABLE (1) -#define MM_MXLOGGER_DISABLE_REASON_STOP (0) -#define MM_MXLOGGER_DISABLE_REASON_COLLECTION (1) - -/* ARG - DIRECTION */ -#define MM_MXLOGGER_DIRECTION_DRAM (0) -#define MM_MXLOGGER_DIRECTION_HOST (1) - -/* ARG - CONFIG TABLE */ -#define MM_MXLOGGER_CONFIG_BASE_ADDR (0) - -/* ARG - CONFIG TABLE */ -#define MM_MXLOGGER_SYNC_INDEX (0) - -#define MM_MXLOGGER_PAYLOAD_SZ (MXMGR_MESSAGE_PAYLOAD_SIZE - 2) - -#define MXLOGGER_SYNC_SIZE (10 * 1024) -#define MXLOGGER_IMP_SIZE (102 * 1024) -#define MXLOGGER_RSV_COMMON_SZ (4 * 1024) -#define MXLOGGER_RSV_BT_SZ (4 * 1024) -#define MXLOGGER_RSV_WLAN_SZ (2 * 1024 * 1024) -#define MXLOGGER_RSV_RADIO_SZ (4 * 1024) - -#define MXLOGGER_TOTAL_FIX_BUF (MXLOGGER_SYNC_SIZE + MXLOGGER_IMP_SIZE + \ - MXLOGGER_RSV_COMMON_SZ + MXLOGGER_RSV_BT_SZ + \ - MXLOGGER_RSV_WLAN_SZ + MXLOGGER_RSV_RADIO_SZ) - -#define MXLOGGER_NON_FIX_BUF_ALIGN 32 - -#define MXLOGGER_MAGIG_NUMBER 0xcaba0401 -#define MXLOGGER_MAJOR 0 -#define MXLOGGER_MINOR 0 - -#define NUM_SYNC_RECORDS 256 -#define SYNC_MASK (NUM_SYNC_RECORDS - 1) - -/* Shared memory Layout - * - * |-------------------------| CONFIG - * | CONFIG AREA | - * | ... | - * | *bufs |------| - * | .... | | - * | .... | | - * | -------------------- |<-----| - * | | - * | loc | sz | state |info |---------------------| - * | loc | sz | state |info |---------------------| - * | loc | sz | state |info |---------------------| - * | ... | | - * |-------------------------| Fixed size buffers | - * | SYNC BUFFER |<--------------------| - * |-------------------------| | - * | IMPORTANT EVENTS |<--------------------| - * |-------------------------| | - * | Reserved COMMON |<--------------------| - * |-------------------------| - * | Reserved BT | - * |-------------------------| - * | Reserved WL | - * |-------------------------| - * | Reserved RADIO | - * |-------------------------| Not fixed size buffers - * | MXLOG | - * |-------------------------| - * | UDI | - * |-------------------------| - * | Future buffers (TBD) | - * |-------------------------| - * | Future buffers (TBD) | - * |-------------------------| - */ - -enum mxlogger_buffers { - MXLOGGER_FIRST_FIXED_SZ, - MXLOGGER_SYNC = MXLOGGER_FIRST_FIXED_SZ, - MXLOGGER_IMP, - MXLOGGER_RESERVED_COMMON, - MXLOGGER_RESERVED_BT, - MXLOGGER_RESERVED_WLAN, - MXLOGGER_RESERVED_RADIO, - MXLOGGER_LAST_FIXED_SZ = MXLOGGER_RESERVED_RADIO, - MXLOGGER_MXLOG, - MXLOGGER_UDI, - MXLOGGER_NUM_BUFFERS -}; - -enum mxlogger_sync_event { - MXLOGGER_SYN_SUSPEND, - MXLOGGER_SYN_RESUME, - MXLOGGER_SYN_TOHOST, - MXLOGGER_SYN_TORAM, - MXLOGGER_SYN_LOGCOLLECTION, -}; - -struct mxlogger_sync_record { - u64 tv_sec; /* struct timeval.tv_sec */ - u64 tv_usec; /* struct timeval.tv_usec */ - u64 kernel_time; /* ktime_t */ - u32 sync_event; /* type of sync event*/ - u32 fw_time; - u32 fw_wrap; - u8 reserved[4]; -} __packed; - -struct buffer_desc { - u32 location; /* Buffer location */ - u32 size; /* Buffer sz (in bytes) */ - u32 status; /* buffer status */ - u32 info; /* buffer info */ -} __packed; - -struct mxlogger_config { - u32 magic_number; /* 0xcaba0401 */ - u32 config_major; /* Version Major */ - u32 config_minor; /* Version Minor */ - u32 num_buffers; /* configured buffers */ - scsc_mifram_ref bfds_ref; -} __packed; - -struct mxlogger_config_area { - struct mxlogger_config config; - struct buffer_desc bfds[MXLOGGER_NUM_BUFFERS]; - uint8_t *buffers_start; -} __packed; - -struct log_msg_packet { - uint8_t msg; /* cmd or event id */ - uint8_t arg; - uint8_t payload[MM_MXLOGGER_PAYLOAD_SZ]; -} __packed; - -struct mxlogger { - bool initialized; - bool configured; - bool enabled; - struct scsc_mx *mx; - void *mem; - void *mem_sync_buf; - uint32_t msz; - scsc_mifram_ref mifram_ref; - struct mutex lock; - struct mxlogger_config_area *cfg; - u8 observers; - u8 sync_buffer_index; - /* collection variables */ - bool re_enable; - struct completion rings_serialized_ops; -}; - -int mxlogger_generate_sync_record(struct mxlogger *mxlogger, enum mxlogger_sync_event event); -int mxlogger_dump_shared_memory_to_file(struct mxlogger *mxlogger); -int mxlogger_init(struct scsc_mx *mx, struct mxlogger *mxlogger, uint32_t mem_sz); -void mxlogger_deinit(struct scsc_mx *mx, struct mxlogger *mxlogger); -int mxlogger_start(struct mxlogger *mxlogger); -int mxlogger_register_observer(struct mxlogger *mxlogger, char *name); -int mxlogger_unregister_observer(struct mxlogger *mxlogger, char *name); -int mxlogger_register_global_observer(char *name); -int mxlogger_unregister_global_observer(char *name); -bool mxlogger_set_enabled_status(bool enable); - -#define MEM_LAYOUT_CHECK() \ -({ \ - BUILD_BUG_ON((sizeof(struct mxlogger_sync_record) * NUM_SYNC_RECORDS) > MXLOGGER_SYNC_SIZE); \ - BUILD_BUG_ON((MXLOGGER_TOTAL_FIX_BUF + sizeof(struct mxlogger_config_area)) > MXL_POOL_SZ); \ -}) - -#endif /* __MX_LOGGER_H__ */ diff --git a/drivers/misc/samsung/scsc/mxman.c b/drivers/misc/samsung/scsc/mxman.c deleted file mode 100755 index 48bce58f9cc1..000000000000 --- a/drivers/misc/samsung/scsc/mxman.c +++ /dev/null @@ -1,2797 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "scsc_mx_impl.h" -#include "miframman.h" -#include "mifmboxman.h" -#include "mxman.h" -#include "srvman.h" -#include "mxmgmt_transport.h" -#include "gdb_transport.h" -#include "mxconf.h" -#include "fwimage.h" -#include "fwhdr.h" -#include "mxlog.h" -#include "mxlogger.h" -#include "fw_panic_record.h" -#include "panicmon.h" -#include "mxproc.h" -#include "mxlog_transport.h" -#include "mxsyserr.h" -#ifdef CONFIG_SCSC_SMAPPER -#include "mifsmapper.h" -#endif -#ifdef CONFIG_SCSC_QOS -#include "mifqos.h" -#endif -#include "mxfwconfig.h" -#include -#include -#include -#include -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif - -#include -#ifdef CONFIG_SCSC_WLBTD -#include "scsc_wlbtd.h" -#define SCSC_SCRIPT_MOREDUMP "moredump" -#define SCSC_SCRIPT_LOGGER_DUMP "mx_logger_dump.sh" -static struct work_struct wlbtd_work; -#endif - -#include "scsc_lerna.h" - -#include -#include - -#define STRING_BUFFER_MAX_LENGTH 512 -#define NUMBER_OF_STRING_ARGS 5 -#define MX_DRAM_SIZE (4 * 1024 * 1024) -#define MX_DRAM_SIZE_SECTION_1 (8 * 1024 * 1024) -#define MX_DRAM_SIZE_SECTION_2 (8 * 1024 * 1024) -#define MX_FW_RUNTIME_LENGTH (1024 * 1024) -#define WAIT_FOR_FW_TO_START_DELAY_MS 1000 -#define MBOX2_MAGIC_NUMBER 0xbcdeedcb -#define MBOX_INDEX_0 0 -#define MBOX_INDEX_1 1 -#define MBOX_INDEX_2 2 -#define MBOX_INDEX_3 3 -#ifdef CONFIG_SOC_EXYNOS7570 -#define MBOX_INDEX_4 4 -#define MBOX_INDEX_5 5 -#define MBOX_INDEX_6 6 -#define MBOX_INDEX_7 7 -#endif - -#define SCSC_PANIC_ORIGIN_FW (0x0 << 15) -#define SCSC_PANIC_ORIGIN_HOST (0x1 << 15) - -#define SCSC_PANIC_TECH_WLAN (0x0 << 13) -#define SCSC_PANIC_TECH_CORE (0x1 << 13) -#define SCSC_PANIC_TECH_BT (0x2 << 13) -#define SCSC_PANIC_TECH_UNSP (0x3 << 13) - -#define SCSC_PANIC_CODE_MASK 0xFFFF -#define SCSC_PANIC_ORIGIN_MASK 0x8000 -#define SCSC_PANIC_TECH_MASK 0x6000 -#define SCSC_PANIC_SUBCODE_MASK_LEGACY 0x0FFF -#define SCSC_PANIC_SUBCODE_MASK 0x7FFF - -#define SCSC_R4_V2_MINOR_52 52 -#define SCSC_R4_V2_MINOR_53 53 - -#define MM_HALT_RSP_TIMEOUT_MS 100 - -static char panic_record_dump[PANIC_RECORD_DUMP_BUFFER_SZ]; -static BLOCKING_NOTIFIER_HEAD(firmware_chain); - -/** - * This will be returned as fw version ONLY if Maxwell - * was never found or was unloaded. - */ -static char saved_fw_build_id[FW_BUILD_ID_SZ] = "Maxwell WLBT unavailable"; - -static bool allow_unidentified_firmware; -module_param(allow_unidentified_firmware, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(allow_unidentified_firmware, "Allow unidentified firmware"); - -static bool skip_header; -module_param(skip_header, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(skip_header, "Skip header, assuming unidentified firmware"); - -static bool crc_check_allow_none = true; -module_param(crc_check_allow_none, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(crc_check_allow_none, "Allow skipping firmware CRC checks if CRC is not present"); - -static int crc_check_period_ms = 30000; -module_param(crc_check_period_ms, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(crc_check_period_ms, "Time period for checking the firmware CRCs"); - -static ulong mm_completion_timeout_ms = 2000; -module_param(mm_completion_timeout_ms, ulong, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mm_completion_timeout_ms, "Timeout wait_for_mm_msg_start_ind (ms) - default 1000. 0 = infinite"); - -static bool skip_mbox0_check; -module_param(skip_mbox0_check, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(skip_mbox0_check, "Allow skipping firmware mbox0 signature check"); - -static uint firmware_startup_flags; -module_param(firmware_startup_flags, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(firmware_startup_flags, "0 = Proceed as normal (default); Bit 0 = 1 - spin at start of CRT0; Other bits reserved = 0"); - -#ifdef CONFIG_SCSC_CHV_SUPPORT -/* First arg controls chv function */ -int chv_run; -module_param(chv_run, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(chv_run, "Run chv f/w: 0 = feature disabled, 1 = for continuous checking, 2 = 1 shot, anything else, undefined"); - -/* Optional array of args for firmware to interpret when chv_run = 1 */ -static unsigned int chv_argv[32]; -static int chv_argc; - -module_param_array(chv_argv, uint, &chv_argc, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(chv_argv, "Array of up to 32 x u32 args for the CHV firmware when chv_run = 1"); -#endif - -static bool disable_auto_coredump; -module_param(disable_auto_coredump, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(disable_auto_coredump, "Disable driver automatic coredump"); - -static bool disable_error_handling; -module_param(disable_error_handling, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(disable_error_handling, "Disable error handling"); - -int disable_recovery_handling = 1; /* MEMDUMP_FILE_FOR_RECOVERY : for /sys/wifi/memdump */ -module_param(disable_recovery_handling, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(disable_recovery_handling, "Disable recovery handling"); -static bool disable_recovery_from_memdump_file = true; -static int memdump = -1; -static bool disable_recovery_until_reboot; - -static uint panic_record_delay = 1; -module_param(panic_record_delay, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(panic_record_delay, "Delay in ms before accessing the panic record"); - -static bool disable_logger = true; -module_param(disable_logger, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(disable_logger, "Disable launch of user space logger"); - -/* - * shared between this module and mgt.c as this is the kobject referring to - * /sys/wifi directory. Core driver is called 1st we create the directory - * here and share the kobject, so in mgt.c wifi driver can create - * /sys/wif/mac_addr using sysfs_create_file api using the kobject - * - * If both modules tried to create the dir we were getting kernel panic - * failure due to kobject associated with dir already existed - */ -static struct kobject *wifi_kobj_ref; -static int refcount; -static ssize_t sysfs_show_memdump(struct kobject *kobj, struct kobj_attribute *attr, - char *buf); -static ssize_t sysfs_store_memdump(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count); -static struct kobj_attribute memdump_attr = - __ATTR(memdump, 0660, sysfs_show_memdump, sysfs_store_memdump); - - -#ifdef CONFIG_SCSC_LOG_COLLECTION -static int mxman_minimoredump_collect(struct scsc_log_collector_client *collect_client, size_t size) -{ - int ret = 0; - struct mxman *mxman = (struct mxman *) collect_client->prv; - - if (!mxman || !mxman->start_dram) - return ret; - - SCSC_TAG_INFO(MXMAN, "Collecting Minimoredump runtime_length %d fw_image_size %d\n", - mxman->fwhdr.fw_runtime_length, mxman->fw_image_size); - /* collect RAM sections of FW */ - ret = scsc_log_collector_write(mxman->start_dram + mxman->fw_image_size, - mxman->fwhdr.fw_runtime_length - mxman->fw_image_size, 1); - - return ret; -} - -struct scsc_log_collector_client mini_moredump_client = { - .name = "minimoredump", - .type = SCSC_LOG_MINIMOREDUMP, - .collect_init = NULL, - .collect = mxman_minimoredump_collect, - .collect_end = NULL, - .prv = NULL, -}; -#endif - -/* Retrieve memdump in sysfs global */ -static ssize_t sysfs_show_memdump(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", memdump); -} - -/* Update memdump in sysfs global */ -static ssize_t sysfs_store_memdump(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, - size_t count) -{ - int r; - - r = kstrtoint(buf, 10, &memdump); - if (r < 0) - memdump = -1; - - switch (memdump) { - case 0: - case 2: - disable_recovery_from_memdump_file = false; - break; - case 3: - default: - disable_recovery_from_memdump_file = true; - break; - } - - SCSC_TAG_INFO(MXMAN, "memdump: %d\n", memdump); - - return (r == 0) ? count : 0; -} - -struct kobject *mxman_wifi_kobject_ref_get(void) -{ - if (refcount++ == 0) { - /* Create sysfs directory /sys/wifi */ - wifi_kobj_ref = kobject_create_and_add("wifi", NULL); - kobject_get(wifi_kobj_ref); - kobject_uevent(wifi_kobj_ref, KOBJ_ADD); - SCSC_TAG_INFO(MXMAN, "wifi_kobj_ref: 0x%p\n", wifi_kobj_ref); - WARN_ON(refcount == 0); - } - return wifi_kobj_ref; -} -EXPORT_SYMBOL(mxman_wifi_kobject_ref_get); - -void mxman_wifi_kobject_ref_put(void) -{ - if (--refcount == 0) { - kobject_put(wifi_kobj_ref); - kobject_uevent(wifi_kobj_ref, KOBJ_REMOVE); - wifi_kobj_ref = NULL; - WARN_ON(refcount < 0); - } -} -EXPORT_SYMBOL(mxman_wifi_kobject_ref_put); - -/* Register memdump override */ -void mxman_create_sysfs_memdump(void) -{ - int r; - struct kobject *kobj_ref = mxman_wifi_kobject_ref_get(); - - SCSC_TAG_INFO(MXMAN, "kobj_ref: 0x%p\n", kobj_ref); - - if (kobj_ref) { - /* Create sysfs file /sys/wifi/memdump */ - r = sysfs_create_file(kobj_ref, &memdump_attr.attr); - if (r) { - /* Failed, so clean up dir */ - SCSC_TAG_ERR(MXMAN, "Can't create /sys/wifi/memdump\n"); - mxman_wifi_kobject_ref_put(); - return; - } - } else { - SCSC_TAG_ERR(MXMAN, "failed to create /sys/wifi directory"); - } -} - -/* Unregister memdump override */ -void mxman_destroy_sysfs_memdump(void) -{ - if (!wifi_kobj_ref) - return; - - /* Destroy /sys/wifi/memdump file */ - sysfs_remove_file(wifi_kobj_ref, &memdump_attr.attr); - - /* Destroy /sys/wifi virtual dir */ - mxman_wifi_kobject_ref_put(); -} - -/* Track when WLBT reset fails to allow debug */ -bool reset_failed; -static u64 reset_failed_time; - -/* Status of FM driver request, which persists beyond the lifecyle - * of the scsx_mx driver. - */ -#ifdef CONFIG_SCSC_FM -static u32 is_fm_on; -#endif - -static int firmware_runtime_flags; -static int syserr_command; -/** - * This mxman reference is initialized/nullified via mxman_init/deinit - * called by scsc_mx_create/destroy on module probe/remove. - */ -static struct mxman *active_mxman; -static bool send_fw_config_to_active_mxman(uint32_t fw_runtime_flags); -static bool send_syserr_cmd_to_active_mxman(u32 syserr_cmd); - -static int fw_runtime_flags_setter(const char *val, const struct kernel_param *kp) -{ - int ret = -EINVAL; - uint32_t fw_runtime_flags = 0; - - if (!val) - return ret; - ret = kstrtouint(val, 10, &fw_runtime_flags); - if (!ret) { - if (send_fw_config_to_active_mxman(fw_runtime_flags)) - firmware_runtime_flags = fw_runtime_flags; - else - ret = -EINVAL; - } - return ret; -} - -/** - * We don't bother to keep an updated copy of the runtime flags effectively - * currently set into FW...we should add a new message answer handling both in - * Kenrel and FW side to be sure and this is just to easy debug at the end. - */ -static struct kernel_param_ops fw_runtime_kops = { - .set = fw_runtime_flags_setter, - .get = NULL -}; - -module_param_cb(firmware_runtime_flags, &fw_runtime_kops, NULL, 0200); -MODULE_PARM_DESC(firmware_runtime_flags, - "0 = Proceed as normal (default); nnn = Provides FW runtime flags bitmask: unknown bits will be ignored."); - -static int syserr_setter(const char *val, const struct kernel_param *kp) -{ - int ret = -EINVAL; - u32 syserr_cmd = 0; - - if (!val) - return ret; - ret = kstrtouint(val, 10, &syserr_cmd); - if (!ret) { - u8 sub_system = (u8)(syserr_cmd / 10); - u8 level = (u8)(syserr_cmd % 10); - - if (((sub_system > 2) && (sub_system < 8)) || (sub_system > 8) || (level > 7)) - ret = -EINVAL; - else if (send_syserr_cmd_to_active_mxman(syserr_cmd)) - syserr_command = syserr_cmd; - else - ret = -EINVAL; - } - return ret; -} - -static struct kernel_param_ops syserr_kops = { - .set = syserr_setter, - .get = NULL -}; - -module_param_cb(syserr_command, &syserr_kops, NULL, 0200); -MODULE_PARM_DESC(syserr_command, - "Decimal XY - Trigger Type X(0,1,2,8), Level Y(1-7). Some combinations not supported"); - -/** - * Maxwell Agent Management Messages. - * - * TODO: common defn with firmware, generated. - * - * The numbers here *must* match the firmware! - */ -enum { - MM_START_IND = 0, - MM_HALT_REQ = 1, - MM_FORCE_PANIC = 2, - MM_HOST_SUSPEND = 3, - MM_HOST_RESUME = 4, - MM_FW_CONFIG = 5, - MM_HALT_RSP = 6, - MM_FM_RADIO_CONFIG = 7, - MM_LERNA_CONFIG = 8, - MM_SYSERR_IND = 9, - MM_SYSERR_CMD = 10 -} ma_msg; - -/** - * Format of the Maxwell agent messages - * on the Maxwell management transport stream. - */ -struct ma_msg_packet { - - uint8_t ma_msg; /* Message from ma_msg enum */ - uint32_t arg; /* Optional arg set by f/w in some to-host messages */ -} __packed; - -/** - * Special case Maxwell management, carrying FM radio configuration structure - */ -struct ma_msg_packet_fm_radio_config { - - uint8_t ma_msg; /* Message from ma_msg enum */ - struct wlbt_fm_params fm_params; /* FM Radio parameters */ -} __packed; - -static bool send_fw_config_to_active_mxman(uint32_t fw_runtime_flags) -{ - bool ret = false; - struct srvman *srvman = NULL; - - SCSC_TAG_INFO(MXMAN, "\n"); - if (!active_mxman) { - SCSC_TAG_ERR(MXMAN, "Active MXMAN NOT FOUND...cannot send running FW config.\n"); - return ret; - } - - mutex_lock(&active_mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(active_mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&active_mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return ret; - } - - if (active_mxman->mxman_state == MXMAN_STATE_STARTED) { - struct ma_msg_packet message = { .ma_msg = MM_FW_CONFIG, - .arg = fw_runtime_flags }; - - SCSC_TAG_INFO(MXMAN, "MM_FW_CONFIG - firmware_runtime_flags:%d\n", message.arg); - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman->mx), - MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, &message, - sizeof(message)); - ret = true; - } else { - SCSC_TAG_INFO(MXMAN, "MXMAN is NOT STARTED...cannot send MM_FW_CONFIG msg.\n"); - } - mutex_unlock(&active_mxman->mxman_mutex); - - return ret; -} - -static bool send_syserr_cmd_to_active_mxman(u32 syserr_cmd) -{ - bool ret = false; - struct srvman *srvman = NULL; - - SCSC_TAG_INFO(MXMAN, "\n"); - if (!active_mxman) { - SCSC_TAG_ERR(MXMAN, "Active MXMAN NOT FOUND...cannot send running FW config.\n"); - return ret; - } - - mutex_lock(&active_mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(active_mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&active_mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return ret; - } - - if (active_mxman->mxman_state == MXMAN_STATE_STARTED) { - struct ma_msg_packet message = { .ma_msg = MM_SYSERR_CMD, - .arg = syserr_cmd}; - - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_CMD - Args %02d\n", message.arg); - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman->mx), - MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, &message, - sizeof(message)); - ret = true; - } else { - SCSC_TAG_INFO(MXMAN, "MXMAN is NOT STARTED...cannot send MM_SYSERR_CMD msg.\n"); - } - mutex_unlock(&active_mxman->mxman_mutex); - - return ret; -} - -#ifdef CONFIG_SCSC_FM -static bool send_fm_params_to_active_mxman(struct wlbt_fm_params *params) -{ - bool ret = false; - struct srvman *srvman = NULL; - - SCSC_TAG_INFO(MXMAN, "\n"); - if (!active_mxman) { - SCSC_TAG_ERR(MXMAN, "Active MXMAN NOT FOUND...cannot send FM params\n"); - return false; - } - - mutex_lock(&active_mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(active_mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&active_mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return false; - } - - if (active_mxman->mxman_state == MXMAN_STATE_STARTED) { - struct ma_msg_packet_fm_radio_config message = { .ma_msg = MM_FM_RADIO_CONFIG, - .fm_params = *params }; - - SCSC_TAG_INFO(MXMAN, "MM_FM_RADIO_CONFIG\n"); - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman->mx), - MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, &message, - sizeof(message)); - - ret = true; /* Success */ - } else - SCSC_TAG_INFO(MXMAN, "MXMAN is NOT STARTED...cannot send MM_FM_RADIO_CONFIG msg.\n"); - - mutex_unlock(&active_mxman->mxman_mutex); - - return ret; -} -#endif - -static void mxman_stop(struct mxman *mxman); -static void print_mailboxes(struct mxman *mxman); -#ifdef CONFIG_SCSC_WLBTD -static int _mx_exec(char *prog, int wait_exec) __attribute__((unused)); -#else -static int _mx_exec(char *prog, int wait_exec); -#endif -static int wait_for_mm_msg(struct mxman *mxman, struct completion *mm_msg_completion, ulong timeout_ms) -{ - int r; - - (void)mxman; /* unused */ - - if (timeout_ms == 0) { - /* Zero implies infinite wait */ - r = wait_for_completion_interruptible(mm_msg_completion); - /* r = -ERESTARTSYS if interrupted, 0 if completed */ - return r; - } - r = wait_for_completion_timeout(mm_msg_completion, msecs_to_jiffies(timeout_ms)); - if (r == 0) { - SCSC_TAG_ERR(MXMAN, "timeout\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int wait_for_mm_msg_start_ind(struct mxman *mxman) -{ - return wait_for_mm_msg(mxman, &mxman->mm_msg_start_ind_completion, mm_completion_timeout_ms); -} - -static int wait_for_mm_msg_halt_rsp(struct mxman *mxman) -{ - int r; - (void)mxman; /* unused */ - - if (MM_HALT_RSP_TIMEOUT_MS == 0) { - /* Zero implies infinite wait */ - r = wait_for_completion_interruptible(&mxman->mm_msg_halt_rsp_completion); - /* r = -ERESTARTSYS if interrupted, 0 if completed */ - return r; - } - - r = wait_for_completion_timeout(&mxman->mm_msg_halt_rsp_completion, msecs_to_jiffies(MM_HALT_RSP_TIMEOUT_MS)); - if (r) - SCSC_TAG_INFO(MXMAN, "Received MM_HALT_RSP from firmware"); - - return r; -} - -#ifndef CONFIG_SCSC_WLBTD -static int coredump_helper(void) -{ - int r; - int i; - static char mdbin[128]; - - /* Determine path to moredump helper script */ - r = mx140_exe_path(NULL, mdbin, sizeof(mdbin), "moredump"); - if (r) { - SCSC_TAG_ERR(MXMAN, "moredump path error\n"); - return r; - } - - for (i = 0; i < 20; i++) { - r = _mx_exec(mdbin, UMH_WAIT_PROC); - if (r != -EBUSY) - break; - /* If the usermode helper fails with -EBUSY, the userspace is - * likely still frozen from suspend. Back off and retry. - */ - SCSC_TAG_INFO(MXMAN, "waiting for userspace to thaw...\n"); - msleep(1000); - } - - /* Application return codes are in the MSB */ - if (r > 0xffL) - SCSC_TAG_INFO(MXMAN, "moredump.bin exit(%ld), check syslog\n", (r & 0xff00L) >> 8); - - return r; -} -#endif - -static int send_mm_msg_stop_blocking(struct mxman *mxman) -{ - int r; -#ifdef CONFIG_SCSC_FM - struct ma_msg_packet message = { .ma_msg = MM_HALT_REQ, - .arg = mxman->on_halt_ldos_on }; -#else - struct ma_msg_packet message = { .ma_msg = MM_HALT_REQ }; -#endif - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman->mx), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, &message, sizeof(message)); - - r = wait_for_mm_msg_halt_rsp(mxman); - if (r) { - /* - * MM_MSG_HALT_RSP is not implemented in all versions of firmware, so don't treat it's non-arrival - * as an error - */ - SCSC_TAG_INFO(MXMAN, "wait_for_MM_HALT_RSP completed"); - } - - return 0; -} - -static char *chip_version(u32 rf_hw_ver) -{ - switch (rf_hw_ver & 0x00ff) { - default: - break; - case 0x00b0: - if ((rf_hw_ver & 0xff00) > 0x1000) - return "S610/S611"; - else - return "S610"; - case 0x00b1: - return "S612"; - case 0x00b2: - return "S620"; - case 0x0000: -#ifndef CONFIG_SOC_EXYNOS9610 - return "Error: check if RF chip is present"; -#else - return "Unknown"; -#endif - } - return "Unknown"; -} - -/* - * This function is used in this file and in mxproc.c to generate consistent - * RF CHIP VERSION string for logging on console and for storing the same - * in proc/drivers/mxman_info/rf_chip_version file. - */ -int mxman_print_rf_hw_version(struct mxman *mxman, char *buf, const size_t bufsz) -{ - int r; - - r = snprintf(buf, bufsz, "RF_CHIP_VERSION: 0x%04x: %s (0x%02x), EVT%x.%x\n", - mxman->rf_hw_ver, - chip_version(mxman->rf_hw_ver), (mxman->rf_hw_ver & 0x00ff), - ((mxman->rf_hw_ver >> 12) & 0xfU), ((mxman->rf_hw_ver >> 8) & 0xfU)); - - return r; -} - -static void mxman_print_versions(struct mxman *mxman) -{ - char buf[80]; - - memset(buf, '\0', sizeof(buf)); - - (void)mxman_print_rf_hw_version(mxman, buf, sizeof(buf)); - - SCSC_TAG_INFO(MXMAN, "%s", buf); - SCSC_TAG_INFO(MXMAN, "WLBT FW: %s\n", mxman->fw_build_id); - SCSC_TAG_INFO(MXMAN, "WLBT Driver: %d.%d.%d.%d\n", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT); -#ifdef CONFIG_SCSC_WLBTD - scsc_wlbtd_get_and_print_build_type(); -#endif -} - -/** Receive handler for messages from the FW along the maxwell management transport */ -static void mxman_message_handler(const void *message, void *data) -{ - struct mxman *mxman = (struct mxman *)data; - - /* Forward the message to the applicable service to deal with */ - const struct ma_msg_packet *msg = message; - - switch (msg->ma_msg) { - case MM_START_IND: - /* The arg can be used to determine the WLBT/S610 hardware revision */ - SCSC_TAG_INFO(MXMAN, "Received MM_START_IND message from the firmware, arg=0x%04x\n", msg->arg); - mxman->rf_hw_ver = msg->arg; - mxman_print_versions(mxman); - atomic_inc(&mxman->boot_count); - complete(&mxman->mm_msg_start_ind_completion); - break; - case MM_HALT_RSP: - complete(&mxman->mm_msg_halt_rsp_completion); - SCSC_TAG_INFO(MXMAN, "Received MM_HALT_RSP message from the firmware\n"); - break; - case MM_LERNA_CONFIG: - /* Message response to a firmware configuration query. */ - SCSC_TAG_INFO(MXMAN, "Received MM_LERNA_CONFIG message from firmware\n"); - scsc_lerna_response(message); - break; - case MM_SYSERR_IND: - /* System Error report from firmware */ - SCSC_TAG_INFO(MXMAN, "Received MM_SYSERR_IND message from firmware\n"); - mx_syserr_handler(mxman, message); - break; - default: - /* HERE: Unknown message, raise fault */ - SCSC_TAG_WARNING(MXMAN, "Received unknown message from the firmware: msg->ma_msg=%d\n", msg->ma_msg); - break; - } -} - -/* - * This function calulates and checks two or three (depending on crc32_over_binary flag) - * crc32 values in the firmware header. The function will check crc32 over the firmware binary - * (i.e. everything in the file following the header) only if the crc32_over_binary is set to 'true'. - * This includes initialised data regions so it can be used to check when loading but will not be - * meaningful once execution starts. - */ -static int do_fw_crc32_checks(char *fw, u32 fw_image_size, struct fwhdr *fwhdr, bool crc32_over_binary) -{ - int r; - - if ((fwhdr->fw_crc32 == 0 || fwhdr->header_crc32 == 0 || fwhdr->const_crc32 == 0) && crc_check_allow_none == 0) { - SCSC_TAG_ERR(MXMAN, "error: CRC is missing fw_crc32=%d header_crc32=%d crc_check_allow_none=%d\n", - fwhdr->fw_crc32, fwhdr->header_crc32, crc_check_allow_none); - return -EINVAL; - } - - if (fwhdr->header_crc32 == 0 && crc_check_allow_none == 1) { - SCSC_TAG_INFO(MXMAN, "Skipping CRC check header_crc32=%d crc_check_allow_none=%d\n", - fwhdr->header_crc32, crc_check_allow_none); - } else { - /* - * CRC-32-IEEE of all preceding header fields (including other CRCs). - * Always the last word in the header. - */ - r = fwimage_check_fw_header_crc(fw, fwhdr->hdr_length, fwhdr->header_crc32); - if (r) { - SCSC_TAG_ERR(MXMAN, "fwimage_check_fw_header_crc() failed\n"); - return r; - } - } - - if (fwhdr->const_crc32 == 0 && crc_check_allow_none == 1) { - SCSC_TAG_INFO(MXMAN, "Skipping CRC check const_crc32=%d crc_check_allow_none=%d\n", - fwhdr->const_crc32, crc_check_allow_none); - } else { - /* - * CRC-32-IEEE over the constant sections grouped together at start of firmware binary. - * This CRC should remain valid during execution. It can be used by run-time checker on - * host to detect firmware corruption (not all memory masters are subject to MPUs). - */ - r = fwimage_check_fw_const_section_crc(fw, fwhdr->const_crc32, fwhdr->const_fw_length, fwhdr->hdr_length); - if (r) { - SCSC_TAG_ERR(MXMAN, "fwimage_check_fw_const_section_crc() failed\n"); - return r; - } - } - - if (crc32_over_binary) { - if (fwhdr->fw_crc32 == 0 && crc_check_allow_none == 1) - SCSC_TAG_INFO(MXMAN, "Skipping CRC check fw_crc32=%d crc_check_allow_none=%d\n", - fwhdr->fw_crc32, crc_check_allow_none); - else { - /* - * CRC-32-IEEE over the firmware binary (i.e. everything - * in the file following this header). - * This includes initialised data regions so it can be used to - * check when loading but will not be meaningful once execution starts. - */ - r = fwimage_check_fw_crc(fw, fw_image_size, fwhdr->hdr_length, fwhdr->fw_crc32); - if (r) { - SCSC_TAG_ERR(MXMAN, "fwimage_check_fw_crc() failed\n"); - return r; - } - } - } - - return 0; -} - - -static void fw_crc_wq_start(struct mxman *mxman) -{ - if (mxman->check_crc && crc_check_period_ms) - queue_delayed_work(mxman->fw_crc_wq, &mxman->fw_crc_work, msecs_to_jiffies(crc_check_period_ms)); -} - - -static void fw_crc_work_func(struct work_struct *work) -{ - int r; - struct mxman *mxman = container_of((struct delayed_work *)work, struct mxman, fw_crc_work); - - r = do_fw_crc32_checks(mxman->fw, mxman->fw_image_size, &mxman->fwhdr, false); - if (r) { - SCSC_TAG_ERR(MXMAN, "do_fw_crc32_checks() failed r=%d\n", r); - mxman_fail(mxman, SCSC_PANIC_CODE_HOST << 15, __func__); - return; - } - fw_crc_wq_start(mxman); -} - - -static void fw_crc_wq_init(struct mxman *mxman) -{ - mxman->fw_crc_wq = create_singlethread_workqueue("fw_crc_wq"); - INIT_DELAYED_WORK(&mxman->fw_crc_work, fw_crc_work_func); -} - -static void fw_crc_wq_stop(struct mxman *mxman) -{ - mxman->check_crc = false; - cancel_delayed_work(&mxman->fw_crc_work); - flush_workqueue(mxman->fw_crc_wq); -} - -static void fw_crc_wq_deinit(struct mxman *mxman) -{ - fw_crc_wq_stop(mxman); - destroy_workqueue(mxman->fw_crc_wq); -} - -static int transports_init(struct mxman *mxman) -{ - struct mxconf *mxconf; - int r; - struct scsc_mx *mx = mxman->mx; - - /* Initialise mx management stack */ - r = mxmgmt_transport_init(scsc_mx_get_mxmgmt_transport(mx), mx); - if (r) { - SCSC_TAG_ERR(MXMAN, "mxmgmt_transport_init() failed %d\n", r); - return r; - } - - /* Initialise gdb transport for cortex-R4 */ - r = gdb_transport_init(scsc_mx_get_gdb_transport_r4(mx), mx, GDB_TRANSPORT_R4); - if (r) { - SCSC_TAG_ERR(MXMAN, "gdb_transport_init() failed %d\n", r); - mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx)); - return r; - } - - /* Initialise gdb transport for cortex-M4 */ - r = gdb_transport_init(scsc_mx_get_gdb_transport_m4(mx), mx, GDB_TRANSPORT_M4); - if (r) { - SCSC_TAG_ERR(MXMAN, "gdb_transport_init() failed %d\n", r); - gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx)); - mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx)); - return r; - } -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - /* Initialise gdb transport for cortex-M4 */ - r = gdb_transport_init(scsc_mx_get_gdb_transport_m4_1(mx), mx, GDB_TRANSPORT_M4_1); - if (r) { - SCSC_TAG_ERR(MXMAN, "gdb_transport_init() failed %d\n", r); - gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx)); - mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx)); - return r; - } -#endif - - /* Initialise mxlog transport */ - r = mxlog_transport_init(scsc_mx_get_mxlog_transport(mx), mx); - if (r) { - SCSC_TAG_ERR(MXMAN, "mxlog_transport_init() failed %d\n", r); - gdb_transport_release(scsc_mx_get_gdb_transport_m4(mx)); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - gdb_transport_release(scsc_mx_get_gdb_transport_m4_1(mx)); -#endif - gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx)); - mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx)); - return r; - } - - /* - * Allocate & Initialise Infrastructre Config Structure - * including the mx management stack config information. - */ - mxconf = miframman_alloc(scsc_mx_get_ramman(mx), sizeof(struct mxconf), 4, MIFRAMMAN_OWNER_COMMON); - if (!mxconf) { - SCSC_TAG_ERR(MXMAN, "miframman_alloc() failed\n"); - gdb_transport_release(scsc_mx_get_gdb_transport_m4(mx)); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - gdb_transport_release(scsc_mx_get_gdb_transport_m4_1(mx)); -#endif - gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx)); - mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx)); - mxlog_transport_release(scsc_mx_get_mxlog_transport(mx)); - return -ENOMEM; - } - mxman->mxconf = mxconf; - mxconf->magic = MXCONF_MAGIC; - mxconf->version.major = MXCONF_VERSION_MAJOR; - mxconf->version.minor = MXCONF_VERSION_MINOR; - - /* Pass pre-existing FM status to FW */ - mxconf->flags = 0; -#ifdef CONFIG_SCSC_FM - mxconf->flags |= is_fm_on ? MXCONF_FLAGS_FM_ON : 0; -#endif - SCSC_TAG_INFO(MXMAN, "mxconf flags 0x%08x\n", mxconf->flags); - - /* serialise mxmgmt transport */ - mxmgmt_transport_config_serialise(scsc_mx_get_mxmgmt_transport(mx), &mxconf->mx_trans_conf); - /* serialise Cortex-R4 gdb transport */ - gdb_transport_config_serialise(scsc_mx_get_gdb_transport_r4(mx), &mxconf->mx_trans_conf_gdb_r4); - /* serialise Cortex-M4 gdb transport */ - gdb_transport_config_serialise(scsc_mx_get_gdb_transport_m4(mx), &mxconf->mx_trans_conf_gdb_m4); - - /* Default to Fleximac M4_1 monitor channel not in use. - * Allows CONFIG_SCSC_MX450_GDB_SUPPORT to be turned off in Kconfig even though mxconf - * struct v5 defines M4_1 channel - */ - mxconf->mx_trans_conf_gdb_m4_1.from_ap_stream_conf.buf_conf.buffer_loc = 0; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - /* serialise Cortex-M4 gdb transport */ - gdb_transport_config_serialise(scsc_mx_get_gdb_transport_m4_1(mx), &mxconf->mx_trans_conf_gdb_m4_1); -#endif - /* serialise mxlog transport */ - mxlog_transport_config_serialise(scsc_mx_get_mxlog_transport(mx), &mxconf->mxlogconf); - SCSC_TAG_DEBUG(MXMAN, "read_bit_idx=%d write_bit_idx=%d buffer=%p num_packets=%d packet_size=%d read_index=%d write_index=%d\n", - scsc_mx_get_mxlog_transport(mx)->mif_stream.read_bit_idx, - scsc_mx_get_mxlog_transport(mx)->mif_stream.write_bit_idx, - scsc_mx_get_mxlog_transport(mx)->mif_stream.buffer.buffer, - scsc_mx_get_mxlog_transport(mx)->mif_stream.buffer.num_packets, - scsc_mx_get_mxlog_transport(mx)->mif_stream.buffer.packet_size, - *scsc_mx_get_mxlog_transport(mx)->mif_stream.buffer.read_index, - *scsc_mx_get_mxlog_transport(mx)->mif_stream.buffer.write_index - ); - - /* Need to initialise fwconfig or else random data can make firmware data abort. */ - mxconf->fwconfig.offset = 0; - mxconf->fwconfig.size = 0; -#ifdef CONFIG_SCSC_COMMON_HCF - /* Load Common Config HCF */ - mxfwconfig_load(mxman->mx, &mxconf->fwconfig); -#endif - return 0; -} - -static void transports_release(struct mxman *mxman) -{ - mxlog_transport_release(scsc_mx_get_mxlog_transport(mxman->mx)); - mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mxman->mx)); - gdb_transport_release(scsc_mx_get_gdb_transport_r4(mxman->mx)); - gdb_transport_release(scsc_mx_get_gdb_transport_m4(mxman->mx)); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - gdb_transport_release(scsc_mx_get_gdb_transport_m4_1(mxman->mx)); -#endif - miframman_free(scsc_mx_get_ramman(mxman->mx), mxman->mxconf); -} - -static void mbox_init(struct mxman *mxman, u32 firmware_entry_point) -{ - u32 *mbox0; - u32 *mbox1; - u32 *mbox2; - u32 *mbox3; - scsc_mifram_ref mifram_ref; - struct scsc_mx *mx = mxman->mx; - struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(mxman->mx); - - /* Place firmware entry address in MIF MBOX 0 so R4 ROM knows where to jump to! */ - mbox0 = mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx), mif, MBOX_INDEX_0); - mbox1 = mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx), mif, MBOX_INDEX_1); - - /* Write (and flush) entry point to MailBox 0, config address to MBOX 1 */ - *mbox0 = firmware_entry_point; - mif->get_mifram_ref(mif, mxman->mxconf, &mifram_ref); - *mbox1 = mifram_ref; /* must be R4-relative address here */ - /* CPU memory barrier */ - wmb(); - /* - * write the magic number "0xbcdeedcb" to MIF Mailbox #2 & - * copy the firmware_startup_flags to MIF Mailbox #3 before starting (reset = 0) the R4 - */ - mbox2 = mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx), mif, MBOX_INDEX_2); - *mbox2 = MBOX2_MAGIC_NUMBER; - mbox3 = mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx), mif, MBOX_INDEX_3); - *mbox3 = firmware_startup_flags; -} - -static int fwhdr_init(char *fw, struct fwhdr *fwhdr, bool *fwhdr_parsed_ok, bool *check_crc) -{ - /* - * Validate the fw image including checking the firmware header, majic #, version, checksum so on - * then do CRC on the entire image - * - * Derive some values from header - - * - * PORT: assumes little endian - */ - if (skip_header) - *fwhdr_parsed_ok = false; /* Allows the forced start address to be used */ - else - *fwhdr_parsed_ok = fwhdr_parse(fw, fwhdr); - *check_crc = false; - if (*fwhdr_parsed_ok) { - SCSC_TAG_INFO(MXMAN, "FW HEADER version: hdr_major: %d hdr_minor: %d\n", fwhdr->hdr_major, fwhdr->hdr_minor); - switch (fwhdr->hdr_major) { - case 0: - switch (fwhdr->hdr_minor) { - case 2: - *check_crc = true; - break; - default: - SCSC_TAG_ERR(MXMAN, "Unsupported FW HEADER version: hdr_major: %d hdr_minor: %d\n", - fwhdr->hdr_major, fwhdr->hdr_minor); - return -EINVAL; - } - break; - case 1: - *check_crc = true; - break; - default: - SCSC_TAG_ERR(MXMAN, "Unsupported FW HEADER version: hdr_major: %d hdr_minor: %d\n", - fwhdr->hdr_major, fwhdr->hdr_minor); - return -EINVAL; - } - switch (fwhdr->fwapi_major) { - case 0: - switch (fwhdr->fwapi_minor) { - case 2: - SCSC_TAG_INFO(MXMAN, "FWAPI version: fwapi_major: %d fwapi_minor: %d\n", - fwhdr->fwapi_major, fwhdr->fwapi_minor); - break; - default: - SCSC_TAG_ERR(MXMAN, "Unsupported FWAPI version: fwapi_major: %d fwapi_minor: %d\n", - fwhdr->fwapi_major, fwhdr->fwapi_minor); - return -EINVAL; - } - break; - default: - SCSC_TAG_ERR(MXMAN, "Unsupported FWAPI version: fwapi_major: %d fwapi_minor: %d\n", - fwhdr->fwapi_major, fwhdr->fwapi_minor); - return -EINVAL; - } - } else { - /* This is unidetified pre-header firmware - assume it is built to run at 0xb8000000 == 0 for bootrom */ - if (allow_unidentified_firmware) { - SCSC_TAG_INFO(MXMAN, "Unidentified firmware override\n"); - fwhdr->firmware_entry_point = 0; - fwhdr->fw_runtime_length = MX_FW_RUNTIME_LENGTH; - } else { - SCSC_TAG_ERR(MXMAN, "Unidentified firmware is not allowed\n"); - return -EINVAL; - } - } - return 0; -} - -static int fw_init(struct mxman *mxman, void *start_dram, size_t size_dram, bool *fwhdr_parsed_ok) -{ - int r; - char *build_id; - char *ttid; - u32 fw_image_size; - struct fwhdr *fwhdr = &mxman->fwhdr; - char *fw = start_dram; - - r = mx140_file_download_fw(mxman->mx, start_dram, size_dram, &fw_image_size); - if (r) { - SCSC_TAG_ERR(MXMAN, "mx140_file_download_fw() failed (%d)\n", r); - return r; - } - - r = fwhdr_init(fw, fwhdr, fwhdr_parsed_ok, &mxman->check_crc); - if (r) { - SCSC_TAG_ERR(MXMAN, "fwhdr_init() failed\n"); - return r; - } - mxman->fw = fw; - mxman->fw_image_size = fw_image_size; - if (mxman->check_crc) { - /* do CRC on the entire image */ - r = do_fw_crc32_checks(fw, fw_image_size, &mxman->fwhdr, true); - if (r) { - SCSC_TAG_ERR(MXMAN, "do_fw_crc32_checks() failed\n"); - return r; - } - fw_crc_wq_start(mxman); - } - - if (*fwhdr_parsed_ok) { - build_id = fwhdr_get_build_id(fw, fwhdr); - if (build_id) { - struct slsi_kic_service_info kic_info; - - (void)snprintf(mxman->fw_build_id, sizeof(mxman->fw_build_id), "%s", build_id); - SCSC_TAG_INFO(MXMAN, "Firmware BUILD_ID: %s\n", mxman->fw_build_id); - memcpy(saved_fw_build_id, mxman->fw_build_id, - sizeof(saved_fw_build_id)); - - (void) snprintf(kic_info.ver_str, - min(sizeof(mxman->fw_build_id), sizeof(kic_info.ver_str)), - "%s", mxman->fw_build_id); - kic_info.fw_api_major = fwhdr->fwapi_major; - kic_info.fw_api_minor = fwhdr->fwapi_minor; - kic_info.release_product = SCSC_RELEASE_PRODUCT; - kic_info.host_release_iteration = SCSC_RELEASE_ITERATION; - kic_info.host_release_candidate = SCSC_RELEASE_CANDIDATE; - - slsi_kic_service_information(slsi_kic_technology_type_common, &kic_info); - } else - SCSC_TAG_ERR(MXMAN, "Failed to get Firmware BUILD_ID\n"); - - ttid = fwhdr_get_ttid(fw, fwhdr); - if (ttid) { - (void)snprintf(mxman->fw_ttid, sizeof(mxman->fw_ttid), "%s", ttid); - SCSC_TAG_INFO(MXMAN, "Firmware ttid: %s\n", mxman->fw_ttid); - } - } - - SCSC_TAG_DEBUG(MXMAN, "firmware_entry_point=0x%x fw_runtime_length=%d\n", fwhdr->firmware_entry_point, fwhdr->fw_runtime_length); - - return 0; - -} - -static int mxman_start(struct mxman *mxman) -{ - void *start_dram; - size_t size_dram = MX_DRAM_SIZE; - struct scsc_mif_abs *mif; - struct fwhdr *fwhdr = &mxman->fwhdr; - bool fwhdr_parsed_ok; - void *start_mifram_heap; - u32 length_mifram_heap; - void *start_mifram_heap2; - u32 length_mifram_heap2; - int r; - - if (reset_failed) { - struct timeval tval = ns_to_timeval(reset_failed_time); - - SCSC_TAG_ERR(MXMAN, "previous reset failed at [%6lu.%06ld], ignoring\n", tval.tv_sec, tval.tv_usec); - return -EIO; - } - - (void)snprintf(mxman->fw_build_id, sizeof(mxman->fw_build_id), "unknown"); - - /* If the option is set to skip header, we must allow unidentified f/w */ - if (skip_header) { - SCSC_TAG_INFO(MXMAN, "Ignoring firmware header block\n"); - allow_unidentified_firmware = true; - } - - mif = scsc_mx_get_mif_abs(mxman->mx); - start_dram = mif->map(mif, &size_dram); - - if (!start_dram) { - SCSC_TAG_ERR(MXMAN, "Error allocating dram\n"); - return -ENOMEM; - } - - SCSC_TAG_INFO(MXMAN, "Allocated %zu bytes\n", size_dram); - -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_run) - allow_unidentified_firmware = true; - /* Set up chv arguments. */ - -#endif - - mxman->start_dram = start_dram; - - r = fw_init(mxman, start_dram, size_dram, &fwhdr_parsed_ok); - if (r) { - SCSC_TAG_ERR(MXMAN, "fw_init() failed\n"); - mif->unmap(mif, mxman->start_dram); - return r; - } - - /* set up memory protection (read only) from start_dram to start_dram+fw_length - * rounding up the size if required - */ - start_mifram_heap = (char *)start_dram + fwhdr->fw_runtime_length; - length_mifram_heap = MX_DRAM_SIZE_SECTION_1 - fwhdr->fw_runtime_length; - - - start_mifram_heap2 = (char *)start_dram + MX_DRAM_SIZE_SECTION_2; - - /* ABox reserved at end so adjust length - round to multiple of PAGE_SIZE */ - length_mifram_heap2 = MX_DRAM_SIZE_SECTION_2 - - ((sizeof(struct scsc_bt_audio_abox) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); - - miframman_init(scsc_mx_get_ramman(mxman->mx), start_mifram_heap, length_mifram_heap, start_dram); - miframman_init(scsc_mx_get_ramman2(mxman->mx), start_mifram_heap2, length_mifram_heap2, start_mifram_heap2); - miframabox_init(scsc_mx_get_aboxram(mxman->mx), start_mifram_heap2 + length_mifram_heap2); - mifmboxman_init(scsc_mx_get_mboxman(mxman->mx)); - mifintrbit_init(scsc_mx_get_intrbit(mxman->mx), mif); - mxfwconfig_init(mxman->mx); - - /* Initialise transports */ - r = transports_init(mxman); - if (r) { - SCSC_TAG_ERR(MXMAN, "transports_init() failed\n"); - fw_crc_wq_stop(mxman); - mifintrbit_deinit(scsc_mx_get_intrbit(mxman->mx)); - miframman_deinit(scsc_mx_get_ramman(mxman->mx)); - miframman_deinit(scsc_mx_get_ramman2(mxman->mx)); - miframabox_deinit(scsc_mx_get_aboxram(mxman->mx)); - mifmboxman_deinit(scsc_mx_get_mboxman(mxman->mx)); - /* Release the MIF memory resources */ - mif->unmap(mif, mxman->start_dram); - return r; - } - mbox_init(mxman, fwhdr->firmware_entry_point); - init_completion(&mxman->mm_msg_start_ind_completion); - init_completion(&mxman->mm_msg_halt_rsp_completion); - mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mxman->mx), - MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, - &mxman_message_handler, mxman); - - mxlog_init(scsc_mx_get_mxlog(mxman->mx), mxman->mx, mxman->fw_build_id); -#ifdef CONFIG_SCSC_MXLOGGER - mxlogger_init(mxman->mx, scsc_mx_get_mxlogger(mxman->mx), MXL_POOL_SZ); - -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Register minimoredump client */ - mini_moredump_client.prv = mxman; - scsc_log_collector_register_client(&mini_moredump_client); -#endif -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* Initialize SMAPPER */ - mifsmapper_init(scsc_mx_get_smapper(mxman->mx), mif); -#endif -#ifdef CONFIG_SCSC_QOS - mifqos_init(scsc_mx_get_qos(mxman->mx), mif); -#endif - -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_run) { - int i; - - u32 *p = (u32 *)((u8 *)start_dram + SCSC_CHV_ARGV_ADDR_OFFSET); - - if (chv_argc == 0) { - /* - * Setup the chv f/w arguments. - * Argument of 0 means run once (driver never set this). - * Argument of 1 means run forever. - */ - SCSC_TAG_INFO(MXMAN, "Setting up CHV arguments: start_dram=%p arg=%p, chv_run=%d\n", start_dram, p, chv_run); - *p++ = 1; /* argc */ - *p++ = chv_run == 1 ? 0 : 1; /* arg */ - } else { - /* Pass separate args */ - *p++ = chv_argc; /* argc */ - SCSC_TAG_INFO(MXMAN, "Setting up additional CHV args: chv_argc = %d\n", chv_argc); - - for (i = 0; i < chv_argc; i++) { - SCSC_TAG_INFO(MXMAN, "Setting up additional CHV args: chv_argv[%d]: *(%p) = 0x%x\n", i, p, (u32)chv_argv[i]); - *p++ = (u32)chv_argv[i]; /* arg */ - } - } - } -#endif - mxproc_create_ctrl_proc_dir(&mxman->mxproc, mxman); - panicmon_init(scsc_mx_get_panicmon(mxman->mx), mxman->mx); - - /* Change state to STARTING to allow coredump as we come out of reset */ - mxman->mxman_state = MXMAN_STATE_STARTING; - - /* release Maxwell from reset */ - r = mif->reset(mif, 0); - if (r) { - reset_failed = true; - SCSC_TAG_INFO(MXMAN, "HW reset deassertion failed\n"); - - /* Save log at point of failure */ -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_schedule_collection(SCSC_LOG_HOST_COMMON, SCSC_LOG_HOST_COMMON_REASON_START); -#else - mx140_log_dump(); -#endif - } - if (fwhdr_parsed_ok) { - r = wait_for_mm_msg_start_ind(mxman); - if (r) { - SCSC_TAG_ERR(MXMAN, "wait_for_MM_START_IND() failed: r=%d\n", r); - print_mailboxes(mxman); - if (skip_mbox0_check) { - SCSC_TAG_ERR(MXMAN, "timeout ignored in skip_mbox0_check mode\n"); - return 0; - } - mxman_stop(mxman); - return r; - } -#ifdef CONFIG_SCSC_MXLOGGER - mxlogger_start(scsc_mx_get_mxlogger(mxman->mx)); -#endif - } else { - msleep(WAIT_FOR_FW_TO_START_DELAY_MS); - } - - return 0; -} - -static bool is_bug_on_enabled(struct scsc_mx *mx) -{ - bool bug_on_enabled; - const struct firmware *firm; - int r; - - if (memdump == 3) - bug_on_enabled = true; - else - bug_on_enabled = false; -#ifdef CONFIG_SCSC_LOG_COLLECTION - (void)firm; /* unused */ - (void)r; /* unused */ - return bug_on_enabled; -#else - /* non SABLE platforms should also follow /sys/wifi/memdump if enabled */ - if (disable_recovery_handling == MEMDUMP_FILE_FOR_RECOVERY) - return bug_on_enabled; - - /* for legacy platforms (including Andorid P) using .memdump.info */ -#if defined(ANDROID_VERSION) && (ANDROID_VERSION >= 90000) - #define MX140_MEMDUMP_INFO_FILE "/data/vendor/conn/.memdump.info" -#else - #define MX140_MEMDUMP_INFO_FILE "/data/misc/conn/.memdump.info" -#endif - - SCSC_TAG_INFO(MX_FILE, "Loading %s file\n", MX140_MEMDUMP_INFO_FILE); - r = mx140_request_file(mx, MX140_MEMDUMP_INFO_FILE, &firm); - if (r) { - SCSC_TAG_WARNING(MX_FILE, "Error Loading %s file %d\n", MX140_MEMDUMP_INFO_FILE, r); - return bug_on_enabled; - } - if (firm->size < sizeof(char)) - SCSC_TAG_WARNING(MX_FILE, "file is too small\n"); - else if (*firm->data == '3') - bug_on_enabled = true; - mx140_release_file(mx, firm); - SCSC_TAG_INFO(MX_FILE, "bug_on_enabled %d\n", bug_on_enabled); - return bug_on_enabled; -#endif //CONFIG_SCSC_LOG_COLLECTION -} - -static void print_panic_code_legacy(u16 code) -{ - u16 tech = code & SCSC_PANIC_TECH_MASK; - u16 origin = code & SCSC_PANIC_ORIGIN_MASK; - - SCSC_TAG_INFO(MXMAN, "Decoding panic code=0x%x:\n", code); - switch (origin) { - default: - SCSC_TAG_INFO(MXMAN, "Failed to identify panic origin\n"); - break; - case SCSC_PANIC_ORIGIN_FW: - SCSC_TAG_INFO(MXMAN, "SCSC_PANIC_ORIGIN_FW\n"); - break; - case SCSC_PANIC_ORIGIN_HOST: - SCSC_TAG_INFO(MXMAN, "SCSC_PANIC_ORIGIN_HOST\n"); - break; - } - - switch (tech) { - default: - SCSC_TAG_INFO(MXMAN, "Failed to identify panic technology\n"); - break; - case SCSC_PANIC_TECH_WLAN: - SCSC_TAG_INFO(MXMAN, "SCSC_PANIC_TECH_WLAN\n"); - break; - case SCSC_PANIC_TECH_CORE: - SCSC_TAG_INFO(MXMAN, "SCSC_PANIC_TECH_CORE\n"); - break; - case SCSC_PANIC_TECH_BT: - SCSC_TAG_INFO(MXMAN, "SCSC_PANIC_TECH_BT\n"); - break; - case SCSC_PANIC_TECH_UNSP: - SCSC_TAG_INFO(MXMAN, "PANIC_TECH_UNSP\n"); - break; - } - SCSC_TAG_INFO(MXMAN, "panic subcode=0x%x\n", code & SCSC_PANIC_SUBCODE_MASK_LEGACY); -} - -static void print_panic_code(u16 code) -{ - u16 origin = code & SCSC_PANIC_ORIGIN_MASK; /* Panic origin (host/fw) */ - u16 subcode = code & SCSC_PANIC_SUBCODE_MASK; /* The panic code */ - - SCSC_TAG_INFO(MXMAN, "Decoding panic code=0x%x:\n", code); - SCSC_TAG_INFO(MXMAN, "panic subcode=0x%x\n", code & SCSC_PANIC_SUBCODE_MASK); - - switch (origin) { - default: - SCSC_TAG_INFO(MXMAN, "Failed to identify panic origin\n"); - break; - case SCSC_PANIC_ORIGIN_FW: - SCSC_TAG_INFO(MXMAN, "WLBT FW PANIC: 0x%02x\n", subcode); - break; - case SCSC_PANIC_ORIGIN_HOST: - SCSC_TAG_INFO(MXMAN, "WLBT HOST detected FW failure, service:\n"); - switch (subcode >> SCSC_SYSERR_HOST_SERVICE_SHIFT) { - case SCSC_SERVICE_ID_WLAN: - SCSC_TAG_INFO(MXMAN, " WLAN\n"); - break; - case SCSC_SERVICE_ID_BT: - SCSC_TAG_INFO(MXMAN, " BT\n"); - break; - case SCSC_SERVICE_ID_ANT: - SCSC_TAG_INFO(MXMAN, " ANT\n"); - break; - case SCSC_SERVICE_ID_CLK20MHZ: - SCSC_TAG_INFO(MXMAN, " CLK20MHZ\n"); - break; - default: - SCSC_TAG_INFO(MXMAN, " Service 0x%x\n", subcode); - break; - } - break; - } -} - -/** - * Print the last panic record collected to aid in post mortem. - * - * Helps when all we have is kernel log showing WLBT failed some time ago - * - * Only prints the R4 record - */ -void mxman_show_last_panic(struct mxman *mxman) -{ - u32 r4_panic_record_length = 0; /* in u32s */ - - /* Any valid panic? */ - if (mxman->scsc_panic_code == 0) - return; - - SCSC_TAG_INFO(MXMAN, "\n\n--- DETAILS OF LAST WLBT FAILURE ---\n\n"); - - switch (mxman->scsc_panic_code & SCSC_PANIC_ORIGIN_MASK) { - case SCSC_PANIC_ORIGIN_HOST: - SCSC_TAG_INFO(MXMAN, "Last panic was host induced:\n"); - break; - - case SCSC_PANIC_ORIGIN_FW: - SCSC_TAG_INFO(MXMAN, "Last panic was FW:\n"); - fw_parse_r4_panic_record(mxman->last_panic_rec_r, &r4_panic_record_length); - break; - - default: - SCSC_TAG_INFO(MXMAN, "Last panic unknown origin %d\n", mxman->scsc_panic_code & SCSC_PANIC_ORIGIN_MASK); - break; - } - - print_panic_code(mxman->scsc_panic_code); - - SCSC_TAG_INFO(MXMAN, "Reason: '%s'\n", mxman->failure_reason[0] ? mxman->failure_reason : ""); - SCSC_TAG_INFO(MXMAN, "Auto-recovery: %s\n", disable_recovery_handling ? "off" : "on"); - - if (mxman_recovery_disabled()) { - /* Labour the point that a reboot is needed when autorecovery is disabled */ - SCSC_TAG_INFO(MXMAN, "\n\n*** HANDSET REBOOT NEEDED TO RESTART WLAN AND BT ***\n\n"); - } - - SCSC_TAG_INFO(MXMAN, "\n\n--- END DETAILS OF LAST WLBT FAILURE ---\n\n"); -} - -static void process_panic_record(struct mxman *mxman) -{ - u32 *r4_panic_record = NULL; - u32 *m4_panic_record = NULL; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - u32 *m4_1_panic_record = NULL; -#endif - u32 r4_panic_record_length = 0; /* in u32s */ - u32 m4_panic_record_length = 0; /* in u32s */ -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - u32 m4_1_panic_record_length = 0; /* in u32s */ -#endif - u32 full_panic_code = 0; - bool r4_panic_record_ok = false; - bool m4_panic_record_ok = false; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - bool m4_1_panic_record_ok = false; -#endif - bool r4_sympathetic_panic_flag = false; - bool m4_sympathetic_panic_flag = false; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - bool m4_1_sympathetic_panic_flag = false; -#endif - - /* some configurable delay before accessing the panic record */ - msleep(panic_record_delay); - /* - * Check if the panic was trigered by MX and set the subcode if so. - */ - if ((mxman->scsc_panic_code & SCSC_PANIC_ORIGIN_MASK) == SCSC_PANIC_ORIGIN_FW) { - if (mxman->fwhdr.r4_panic_record_offset) { - r4_panic_record = (u32 *)(mxman->fw + mxman->fwhdr.r4_panic_record_offset); - r4_panic_record_ok = fw_parse_r4_panic_record(r4_panic_record, &r4_panic_record_length); - } else { - SCSC_TAG_INFO(MXMAN, "R4 panic record doesn't exist in the firmware header\n"); - } - if (mxman->fwhdr.m4_panic_record_offset) { - m4_panic_record = (u32 *)(mxman->fw + mxman->fwhdr.m4_panic_record_offset); - m4_panic_record_ok = fw_parse_m4_panic_record(m4_panic_record, &m4_panic_record_length); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - } else if (mxman->fwhdr.m4_1_panic_record_offset) { - m4_1_panic_record = (u32 *)(mxman->fw + mxman->fwhdr.m4_1_panic_record_offset); - m4_1_panic_record_ok = fw_parse_m4_panic_record(m4_panic_record, &m4_1_panic_record_length); -#endif - } else { - SCSC_TAG_INFO(MXMAN, "M4 panic record doesn't exist in the firmware header\n"); - } - - /* Extract and print the panic code */ - switch (r4_panic_record_length) { - default: - SCSC_TAG_WARNING(MXMAN, "Bad panic record length/subversion\n"); - break; - case SCSC_R4_V2_MINOR_52: - if (r4_panic_record_ok) { - full_panic_code = r4_panic_record[2]; - mxman->scsc_panic_code |= SCSC_PANIC_CODE_MASK & full_panic_code; - } else if (m4_panic_record_ok) - mxman->scsc_panic_code |= SCSC_PANIC_CODE_MASK & m4_panic_record[2]; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - else if (m4_1_panic_record_ok) - mxman->scsc_panic_code |= SCSC_PANIC_CODE_MASK & m4_1_panic_record[2]; -#endif - /* Set unspecified technology for now */ - mxman->scsc_panic_code |= SCSC_PANIC_TECH_UNSP; - print_panic_code_legacy(mxman->scsc_panic_code); - break; - case SCSC_R4_V2_MINOR_53: - if (r4_panic_record_ok) { - /* Save the last R4 panic record for future display */ - BUG_ON(sizeof(mxman->last_panic_rec_r) < SCSC_R4_V2_MINOR_53 * sizeof(u32)); - memcpy((u8 *)mxman->last_panic_rec_r, (u8 *)r4_panic_record, SCSC_R4_V2_MINOR_53 * sizeof(u32)); - mxman->last_panic_rec_sz = r4_panic_record_length; - - r4_sympathetic_panic_flag = fw_parse_get_r4_sympathetic_panic_flag(r4_panic_record); - SCSC_TAG_INFO(MXMAN, "r4_panic_record_ok=%d r4_sympathetic_panic_flag=%d\n", - r4_panic_record_ok, - r4_sympathetic_panic_flag - ); - if (r4_sympathetic_panic_flag == false) { - /* process R4 record */ - SCSC_TAG_INFO(MXMAN, "process R4 record\n"); - full_panic_code = r4_panic_record[3]; - mxman->scsc_panic_code |= SCSC_PANIC_CODE_MASK & full_panic_code; - print_panic_code(mxman->scsc_panic_code); - break; - } - } - if (m4_panic_record_ok) { - m4_sympathetic_panic_flag = fw_parse_get_m4_sympathetic_panic_flag(m4_panic_record); - SCSC_TAG_INFO(MXMAN, "m4_panic_record_ok=%d m4_sympathetic_panic_flag=%d\n", - m4_panic_record_ok, - m4_sympathetic_panic_flag - ); - if (m4_sympathetic_panic_flag == false) { - /* process M4 record */ - SCSC_TAG_INFO(MXMAN, "process M4 record\n"); - mxman->scsc_panic_code |= SCSC_PANIC_CODE_MASK & m4_panic_record[3]; - } else if (r4_panic_record_ok) { - /* process R4 record */ - SCSC_TAG_INFO(MXMAN, "process R4 record\n"); - mxman->scsc_panic_code |= SCSC_PANIC_CODE_MASK & r4_panic_record[3]; - } - print_panic_code(mxman->scsc_panic_code); - } -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT /* this is wrong but not sure what is "right" */ -/* "sympathetic panics" are not really a thing on the Neus architecture unless */ -/* generated by the host */ - if (m4_1_panic_record_ok) { - m4_1_sympathetic_panic_flag = fw_parse_get_m4_sympathetic_panic_flag(m4_panic_record); - SCSC_TAG_INFO(MXMAN, "m4_1_panic_record_ok=%d m4_1_sympathetic_panic_flag=%d\n", - m4_1_panic_record_ok, - m4_1_sympathetic_panic_flag - ); - if (m4_1_sympathetic_panic_flag == false) { - /* process M4 record */ - SCSC_TAG_INFO(MXMAN, "process M4_1 record\n"); - mxman->scsc_panic_code |= SCSC_PANIC_SUBCODE_MASK & m4_1_panic_record[3]; - } else if (r4_panic_record_ok) { - /* process R4 record */ - SCSC_TAG_INFO(MXMAN, "process R4 record\n"); - mxman->scsc_panic_code |= SCSC_PANIC_SUBCODE_MASK & r4_panic_record[3]; - } - print_panic_code(mxman->scsc_panic_code); - } -#endif - break; - } - } - if (r4_panic_record_ok) { - /* Populate syserr info with panic equivalent */ - mxman->last_syserr.subsys = (u8) ((full_panic_code >> SYSERR_SUB_SYSTEM_POSN) & SYSERR_SUB_SYSTEM_MASK); - mxman->last_syserr.level = MX_SYSERR_LEVEL_7; - mxman->last_syserr.type = (u8) ((full_panic_code >> SYSERR_TYPE_POSN) & SYSERR_TYPE_MASK); - mxman->last_syserr.subcode = (u16) ((full_panic_code >> SYSERR_SUB_CODE_POSN) & SYSERR_SUB_CODE_MASK); - } -} - -#define MAX_UHELP_TMO_MS 20000 -/* - * workqueue thread - */ -static void mxman_failure_work(struct work_struct *work) -{ - struct mxman *mxman = container_of(work, struct mxman, failure_work); - struct srvman *srvman; - struct scsc_mx *mx = mxman->mx; - struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(mxman->mx); - int used = 0, r = 0; - -#ifdef CONFIG_ANDROID - wake_lock(&mxman->failure_recovery_wake_lock); -#endif - /* Take mutex shared with syserr recovery */ - mutex_lock(&mxman->mxman_recovery_mutex); - - slsi_kic_system_event(slsi_kic_system_event_category_error, - slsi_kic_system_events_subsystem_crashed, GFP_KERNEL); - - blocking_notifier_call_chain(&firmware_chain, SCSC_FW_EVENT_FAILURE, NULL); - - SCSC_TAG_INFO(MXMAN, "Complete mm_msg_start_ind_completion\n"); - complete(&mxman->mm_msg_start_ind_completion); - mutex_lock(&mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(mxman->mx); - - if (mxman->mxman_state != MXMAN_STATE_STARTED && mxman->mxman_state != MXMAN_STATE_STARTING) { - SCSC_TAG_WARNING(MXMAN, "Not in started state: mxman->mxman_state=%d\n", mxman->mxman_state); -#ifdef CONFIG_ANDROID - wake_unlock(&mxman->failure_recovery_wake_lock); -#endif - mutex_unlock(&mxman->mxman_mutex); - mutex_unlock(&mxman->mxman_recovery_mutex); - return; - } - - /** - * Set error on mxlog and unregister mxlog msg-handlers. - * mxlog ISR and kthread will ignore further messages - * but mxlog_thread is NOT stopped here. - */ - mxlog_transport_set_error(scsc_mx_get_mxlog_transport(mx)); - mxlog_release(scsc_mx_get_mxlog(mx)); - /* unregister channel handler */ - mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mx), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, - NULL, NULL); - mxmgmt_transport_set_error(scsc_mx_get_mxmgmt_transport(mx)); - srvman_set_error(srvman); - fw_crc_wq_stop(mxman); - - mxman->mxman_state = mxman->mxman_next_state; - - /* Mark any single service recovery as no longer in progress */ - mxman->syserr_recovery_in_progress = false; - mxman->last_syserr_recovery_time = 0; - - /* Safe to allow syserr recovery thread to run */ - mutex_unlock(&mxman->mxman_recovery_mutex); - - if (mxman->mxman_state != MXMAN_STATE_FAILED - && mxman->mxman_state != MXMAN_STATE_FROZEN) { - WARN_ON(mxman->mxman_state != MXMAN_STATE_FAILED - && mxman->mxman_state != MXMAN_STATE_FROZEN); - SCSC_TAG_ERR(MXMAN, "Bad state=%d\n", mxman->mxman_state); -#ifdef CONFIG_ANDROID - wake_unlock(&mxman->failure_recovery_wake_lock); -#endif - mutex_unlock(&mxman->mxman_mutex); - return; - } - /* Signal panic to r4 and m4 processors */ - SCSC_TAG_INFO(MXMAN, "Setting MIFINTRBIT_RESERVED_PANIC_R4\n"); - mif->irq_bit_set(mif, MIFINTRBIT_RESERVED_PANIC_R4, SCSC_MIF_ABS_TARGET_R4); /* SCSC_MIFINTR_TARGET_R4 */ -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - SCSC_TAG_INFO(MXMAN, "Setting MIFINTRBIT_RESERVED_PANIC_M4\n"); - mif->irq_bit_set(mif, MIFINTRBIT_RESERVED_PANIC_M4, SCSC_MIF_ABS_TARGET_M4); /* SCSC_MIFINTR_TARGET_M4 */ - SCSC_TAG_INFO(MXMAN, "Setting MIFINTRBIT_RESERVED_PANIC_M4_1\n"); - mif->irq_bit_set(mif, MIFINTRBIT_RESERVED_PANIC_M4_1, SCSC_MIF_ABS_TARGET_M4_1); /* SCSC_MIFINTR_TARGET_M4 */ -#else - SCSC_TAG_INFO(MXMAN, "Setting MIFINTRBIT_RESERVED_PANIC_M4\n"); - mif->irq_bit_set(mif, MIFINTRBIT_RESERVED_PANIC_M4, SCSC_MIF_ABS_TARGET_M4); /* SCSC_MIFINTR_TARGET_M4 */ -#endif - srvman_freeze_services(srvman, &mxman->last_syserr); - if (mxman->mxman_state == MXMAN_STATE_FAILED) { - mxman->last_panic_time = local_clock(); - process_panic_record(mxman); - SCSC_TAG_INFO(MXMAN, "Trying to schedule coredump\n"); - SCSC_TAG_INFO(MXMAN, "scsc_release %d.%d.%d.%d\n", - SCSC_RELEASE_PRODUCT, - SCSC_RELEASE_ITERATION, - SCSC_RELEASE_CANDIDATE, - SCSC_RELEASE_POINT); - SCSC_TAG_INFO(MXMAN, "Auto-recovery: %s\n", mxman_recovery_disabled() ? "off" : "on"); -#ifdef CONFIG_SCSC_WLBTD - scsc_wlbtd_get_and_print_build_type(); -#endif - - /* schedule coredump and wait for it to finish */ - if (disable_auto_coredump) { - SCSC_TAG_INFO(MXMAN, "Driver automatic coredump disabled, not launching coredump helper\n"); - } else { - /** - * Releasing mxman_mutex here gives way to any - * eventually running resume process while waiting for - * the usermode helper subsystem to be resurrected, - * since this last will be re-enabled right at the end - * of the resume process itself. - */ - mutex_unlock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, - "waiting up to %dms for usermode_helper subsystem.\n", - MAX_UHELP_TMO_MS); - /* Waits for the usermode_helper subsytem to be re-enabled. */ - if (usermodehelper_read_lock_wait(msecs_to_jiffies(MAX_UHELP_TMO_MS))) { - /** - * Release immediately the rwsem on usermode_helper - * enabled since we anyway already hold a wakelock here - */ - usermodehelper_read_unlock(); - /** - * We claim back the mxman_mutex immediately to avoid anyone - * shutting down the chip while we are dumping the coredump. - */ - mutex_lock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Invoking coredump helper\n"); - slsi_kic_system_event(slsi_kic_system_event_category_recovery, - slsi_kic_system_events_coredump_in_progress, - GFP_KERNEL); -#ifdef CONFIG_SCSC_WLBTD - /* we can safely call call_wlbtd as we are - * in workqueue context - */ -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Collect mxlogger logs */ - scsc_log_collector_schedule_collection(SCSC_LOG_FW_PANIC, mxman->scsc_panic_code); -#else - r = call_wlbtd(SCSC_SCRIPT_MOREDUMP); -#endif -#else - r = coredump_helper(); -#endif - if (r >= 0) { - slsi_kic_system_event(slsi_kic_system_event_category_recovery, - slsi_kic_system_events_coredump_done, GFP_KERNEL); - } - - used = snprintf(panic_record_dump, - PANIC_RECORD_DUMP_BUFFER_SZ, - "RF HW Ver: 0x%X\n", mxman->rf_hw_ver); - used += snprintf(panic_record_dump + used, - PANIC_RECORD_DUMP_BUFFER_SZ - used, - "SCSC Panic Code:: 0x%X\n", mxman->scsc_panic_code); - used += snprintf(panic_record_dump + used, - PANIC_RECORD_DUMP_BUFFER_SZ - used, - "SCSC Last Panic Time:: %lld\n", mxman->last_panic_time); - panic_record_dump_buffer("r4", mxman->last_panic_rec_r, - mxman->last_panic_rec_sz, - panic_record_dump + used, - PANIC_RECORD_DUMP_BUFFER_SZ - used); - - /* Print the host code/reason again so it's near the FW panic - * record in the kernel log - */ - print_panic_code(mxman->scsc_panic_code); - SCSC_TAG_INFO(MXMAN, "Reason: '%s'\n", mxman->failure_reason[0] ? mxman->failure_reason : ""); - - blocking_notifier_call_chain(&firmware_chain, - SCSC_FW_EVENT_MOREDUMP_COMPLETE, - &panic_record_dump); - } else { - SCSC_TAG_INFO(MXMAN, - "timed out waiting for usermode_helper. Skipping coredump.\n"); - mutex_lock(&mxman->mxman_mutex); - } - } - - if (is_bug_on_enabled(mx)) { - SCSC_TAG_ERR(MX_FILE, "Deliberately panic the kernel due to WLBT firmware failure!\n"); - SCSC_TAG_ERR(MX_FILE, "calling BUG_ON(1)\n"); - BUG_ON(1); - } - /* Clean up the MIF following error handling */ - if (mif->mif_cleanup && mxman_recovery_disabled()) - mif->mif_cleanup(mif); - } else { - /* Populate syserr info with panic equivalent for host induced panic */ - mxman->last_syserr.subsys = SYSERR_SUB_SYSTEM_HOST; - mxman->last_syserr.level = MX_SYSERR_LEVEL_7; - mxman->last_syserr.type = 0; - mxman->last_syserr.subcode = mxman->scsc_panic_code; - } - SCSC_TAG_INFO(MXMAN, "Auto-recovery: %s\n", - mxman_recovery_disabled() ? "off" : "on"); - - if (!mxman_recovery_disabled()) - srvman_clear_error(srvman); - mutex_unlock(&mxman->mxman_mutex); - if (!mxman_recovery_disabled()) { - SCSC_TAG_INFO(MXMAN, "Calling srvman_unfreeze_services\n"); - srvman_unfreeze_services(srvman, mxman->scsc_panic_code); - if (scsc_mx_module_reset() < 0) - SCSC_TAG_INFO(MXMAN, "failed to call scsc_mx_module_reset\n"); - atomic_inc(&mxman->recovery_count); - } - - /** - * If recovery is disabled and an scsc_mx_service_open has been hold up, - * release it, rather than wait for the recovery_completion to timeout. - */ - if (mxman_recovery_disabled()) - complete(&mxman->recovery_completion); - -#ifdef CONFIG_ANDROID - wake_unlock(&mxman->failure_recovery_wake_lock); -#endif -} - -static void failure_wq_init(struct mxman *mxman) -{ - mxman->failure_wq = create_singlethread_workqueue("failure_wq"); - INIT_WORK(&mxman->failure_work, mxman_failure_work); -} - -static void failure_wq_stop(struct mxman *mxman) -{ - cancel_work_sync(&mxman->failure_work); - flush_workqueue(mxman->failure_wq); -} - -static void failure_wq_deinit(struct mxman *mxman) -{ - failure_wq_stop(mxman); - destroy_workqueue(mxman->failure_wq); -} - -static void failure_wq_start(struct mxman *mxman) -{ - if (disable_error_handling) - SCSC_TAG_INFO(MXMAN, "error handling disabled\n"); - else - queue_work(mxman->failure_wq, &mxman->failure_work); -} - -/* - * workqueue thread - */ -static void mxman_syserr_recovery_work(struct work_struct *work) -{ - struct mxman *mxman = container_of(work, struct mxman, syserr_recovery_work); - struct srvman *srvman; - -#ifdef CONFIG_ANDROID - wake_lock(&mxman->syserr_recovery_wake_lock); -#endif - if (!mutex_trylock(&mxman->mxman_recovery_mutex)) { - SCSC_TAG_WARNING(MXMAN, "Syserr during full reset - ignored\n"); -#ifdef CONFIG_ANDROID - wake_unlock(&mxman->syserr_recovery_wake_lock); -#endif - return; - } - - mutex_lock(&mxman->mxman_mutex); - - if (mxman->mxman_state != MXMAN_STATE_STARTED && mxman->mxman_state != MXMAN_STATE_STARTING) { - SCSC_TAG_WARNING(MXMAN, "Syserr reset ignored: mxman->mxman_state=%d\n", mxman->mxman_state); -#ifdef CONFIG_ANDROID - wake_unlock(&mxman->syserr_recovery_wake_lock); -#endif - mutex_unlock(&mxman->mxman_mutex); - return; - } - - srvman = scsc_mx_get_srvman(mxman->mx); - - srvman_freeze_sub_system(srvman, &mxman->last_syserr); - -#ifdef CONFIG_SCSC_WLBTD -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Wait for log generation if not finished */ - SCSC_TAG_INFO(MXMAN, "Wait for syserr sable logging\n"); - scsc_wlbtd_wait_for_sable_logging(); - SCSC_TAG_INFO(MXMAN, "Syserr sable logging complete\n"); -#endif -#endif - - srvman_unfreeze_sub_system(srvman, &mxman->last_syserr); - -#ifdef CONFIG_ANDROID - wake_unlock(&mxman->syserr_recovery_wake_lock); -#endif - mutex_unlock(&mxman->mxman_mutex); -} - -static void syserr_recovery_wq_init(struct mxman *mxman) -{ - mxman->syserr_recovery_wq = create_singlethread_workqueue("syserr_recovery_wq"); - INIT_WORK(&mxman->syserr_recovery_work, mxman_syserr_recovery_work); -} - -static void syserr_recovery_wq_stop(struct mxman *mxman) -{ - cancel_work_sync(&mxman->syserr_recovery_work); - flush_workqueue(mxman->syserr_recovery_wq); -} - -static void syserr_recovery_wq_deinit(struct mxman *mxman) -{ - syserr_recovery_wq_stop(mxman); - destroy_workqueue(mxman->syserr_recovery_wq); -} - -static void syserr_recovery_wq_start(struct mxman *mxman) -{ - queue_work(mxman->syserr_recovery_wq, &mxman->syserr_recovery_work); -} - -static void print_mailboxes(struct mxman *mxman) -{ - struct scsc_mif_abs *mif; - struct mifmboxman *mboxman; - int i; - - mif = scsc_mx_get_mif_abs(mxman->mx); - mboxman = scsc_mx_get_mboxman(mxman->mx); - - SCSC_TAG_INFO(MXMAN, "Printing mailbox values:\n"); - for (i = 0; i < MIFMBOX_NUM; i++) - SCSC_TAG_INFO(MXMAN, "MBOX_%d: 0x%x\n", i, *mifmboxman_get_mbox_ptr(mboxman, mif, i)); -} -#ifdef CONFIG_SCSC_WLBTD -static void wlbtd_work_func(struct work_struct *work) -{ - /* require sleep-able workqueue to run successfully */ -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Collect mxlogger logs */ - /* Extend to scsc_log_collector_collect() if required */ -#else - call_wlbtd(SCSC_SCRIPT_LOGGER_DUMP); -#endif -} - -static void wlbtd_wq_init(struct mxman *mx) -{ - INIT_WORK(&wlbtd_work, wlbtd_work_func); -} - -static void wlbtd_wq_deinit(struct mxman *mx) -{ - /* flush and block until work is complete */ - flush_work(&wlbtd_work); -} -#endif -/* - * Check for matching f/w and h/w - * - * Returns 0: f/w and h/w match - * 1: f/w and h/w mismatch, try the next config - * -ve fatal error - */ -static int mxman_hw_ver_check(struct mxman *mxman) -{ - if (mx140_file_supported_hw(mxman->mx, mxman->rf_hw_ver)) - return 0; - else - return 1; -} - -/* - * Select the f/w version to load next - */ -static int mxman_select_next_fw(struct mxman *mxman) -{ - return mx140_file_select_fw(mxman->mx, mxman->rf_hw_ver); -} - -/* Boot MX140 with given f/w */ -static int __mxman_open(struct mxman *mxman) -{ - int r; - struct srvman *srvman; - - mx140_basedir_file(mxman->mx); - - mutex_lock(&mxman->mxman_mutex); - if (mxman->scsc_panic_code) { - SCSC_TAG_INFO(MXMAN, "Previously recorded crash panic code: scsc_panic_code=0x%x\n", mxman->scsc_panic_code); - SCSC_TAG_INFO(MXMAN, "Reason: '%s'\n", mxman->failure_reason[0] ? mxman->failure_reason : ""); - print_panic_code(mxman->scsc_panic_code); - } - SCSC_TAG_INFO(MXMAN, "Auto-recovery: %s\n", mxman_recovery_disabled() ? "off" : "on"); - srvman = scsc_mx_get_srvman(mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return -EINVAL; - } - - /* Reset the state after a previous crash during f/w boot */ - if (mxman->mxman_state == MXMAN_STATE_STARTING) - mxman->mxman_state = MXMAN_STATE_STOPPED; - - if (mxman->mxman_state == MXMAN_STATE_STARTED) { - /* if in the STARTED state there MUST already be some users */ - if (WARN_ON(!mxman->users)) { - SCSC_TAG_ERR(MXMAN, "ERROR mxman->mxman_state=%d users=%d\n", mxman->mxman_state, mxman->users); - mutex_unlock(&mxman->mxman_mutex); - return -EINVAL; - } - mxman->users++; - SCSC_TAG_INFO(MXMAN, "Already opened: users=%d\n", mxman->users); - mxman_print_versions(mxman); - mutex_unlock(&mxman->mxman_mutex); - return 0; - } else if (mxman->mxman_state == MXMAN_STATE_STOPPED) { - r = mxman_start(mxman); - if (r) { - SCSC_TAG_ERR(MXMAN, "maxwell_manager_start() failed r=%d users=%d\n", r, mxman->users); - mutex_unlock(&mxman->mxman_mutex); - return r; - } - mxman->users++; - mxman->mxman_state = MXMAN_STATE_STARTED; - mutex_unlock(&mxman->mxman_mutex); - /* Start mxlogger */ - if (!disable_logger) { - static char mxlbin[128]; - - r = mx140_exe_path(NULL, mxlbin, sizeof(mxlbin), "mx_logger.sh"); - if (r) { - /* Not found */ - SCSC_TAG_ERR(MXMAN, "mx_logger.sh path error\n"); - } else { - /* Launch it */ - _mx_exec(mxlbin, UMH_WAIT_EXEC); - } - } - return 0; - } - WARN_ON(mxman->mxman_state != MXMAN_STATE_STARTED && mxman->mxman_state != MXMAN_STATE_STOPPED); - SCSC_TAG_ERR(MXMAN, "Bad state: mxman->mxman_state=%d\n", mxman->mxman_state); - mutex_unlock(&mxman->mxman_mutex); - return -EIO; -} - -int mxman_open(struct mxman *mxman) -{ - int r; - int try = 0; - - struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(mxman->mx); - - for (try = 0; try < 2; try++) { - /* Boot WLBT. This will determine the h/w version */ - r = __mxman_open(mxman); - if (r) - return r; - - /* On retries, restore USBPLL owner as WLBT */ - if (try > 0 && mif->mif_restart) - mif->mif_restart(mif); - - /* Check the h/w and f/w versions are compatible */ - r = mxman_hw_ver_check(mxman); - if (r > 0) { - /* Not compatible, so try next f/w */ - SCSC_TAG_INFO(MXMAN, "Incompatible h/w 0x%04x vs f/w, close and try next\n", mxman->rf_hw_ver); - - /* Temporarily return USBPLL owner to AP to keep USB alive */ - if (mif->mif_cleanup) - mif->mif_cleanup(mif); - - /* Stop WLBT */ - mxman_close(mxman); - - /* Select the new f/w for this hw ver */ - mxman_select_next_fw(mxman); - } else - break; /* Running or given up */ - } - -#ifdef CONFIG_SCSC_FM - /* If we have stored FM radio parameters, deliver them to FW now */ - if (r == 0 && mxman->fm_params_pending) { - SCSC_TAG_INFO(MXMAN, "Send pending FM params\n"); - mxman_fm_set_params(&mxman->fm_params); - } -#endif - - return r; -} - -static void mxman_stop(struct mxman *mxman) -{ - int r; - struct scsc_mif_abs *mif; - - SCSC_TAG_INFO(MXMAN, "\n"); - - /* If reset is failed, prevent new resets */ - if (reset_failed) { - struct timeval tval = ns_to_timeval(reset_failed_time); - - SCSC_TAG_ERR(MXMAN, "previous reset failed at [%6lu.%06ld], ignoring\n", tval.tv_sec, tval.tv_usec); - return; - } - - (void)snprintf(mxman->fw_build_id, sizeof(mxman->fw_build_id), "unknown"); - - mxproc_remove_ctrl_proc_dir(&mxman->mxproc); - - /* Shutdown the hardware */ - mif = scsc_mx_get_mif_abs(mxman->mx); - r = mif->reset(mif, 1); - if (r) { - reset_failed_time = local_clock(); - SCSC_TAG_INFO(MXMAN, "HW reset failed\n"); - reset_failed = true; - - /* Save log at point of failure */ -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_schedule_collection(SCSC_LOG_HOST_COMMON, SCSC_LOG_HOST_COMMON_REASON_STOP); -#else - mx140_log_dump(); -#endif - } - - panicmon_deinit(scsc_mx_get_panicmon(mxman->mx)); - transports_release(mxman); - mxfwconfig_unload(mxman->mx); - - mxlog_release(scsc_mx_get_mxlog(mxman->mx)); - /* unregister channel handler */ - mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mxman->mx), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, - NULL, NULL); - fw_crc_wq_stop(mxman); - - /* Unitialise components (they may perform some checks - e.g. all memory freed) */ - mxfwconfig_deinit(mxman->mx); - mifintrbit_deinit(scsc_mx_get_intrbit(mxman->mx)); - miframman_deinit(scsc_mx_get_ramman(mxman->mx)); - miframman_deinit(scsc_mx_get_ramman2(mxman->mx)); - miframabox_deinit(scsc_mx_get_aboxram(mxman->mx)); - mifmboxman_deinit(scsc_mx_get_mboxman(mxman->mx)); -#ifdef CONFIG_SCSC_SMAPPER - mifsmapper_deinit(scsc_mx_get_smapper(mxman->mx)); -#endif -#ifdef CONFIG_SCSC_QOS - mifqos_deinit(scsc_mx_get_qos(mxman->mx)); -#endif - /* Release the MIF memory resources */ - mif->unmap(mif, mxman->start_dram); -} - -void mxman_close(struct mxman *mxman) -{ - int r; - struct srvman *srvman; - - mutex_lock(&mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return; - } - - SCSC_TAG_INFO(MXMAN, "\n"); - - if (mxman->mxman_state == MXMAN_STATE_STARTED) { - if (WARN_ON(!mxman->users)) { - SCSC_TAG_ERR(MXMAN, "ERROR users=%d\n", mxman->users); - mutex_unlock(&mxman->mxman_mutex); - return; - } - mxman->users--; - if (mxman->users) { - SCSC_TAG_INFO(MXMAN, "Current number of users=%d\n", mxman->users); - mutex_unlock(&mxman->mxman_mutex); - return; - } -#ifdef CONFIG_SCSC_MXLOGGER -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Unregister minimoredump client */ - scsc_log_collector_unregister_client(&mini_moredump_client); -#endif - /** - * Deinit mxlogger on last service stop...BUT before asking for HALT - */ - mxlogger_deinit(mxman->mx, scsc_mx_get_mxlogger(mxman->mx)); -#endif - /* - * Ask the subsystem to stop (MM_STOP_REQ), and wait - * for response (MM_STOP_RSP). - */ - r = send_mm_msg_stop_blocking(mxman); - if (r) - SCSC_TAG_ERR(MXMAN, "send_mm_msg_stop_blocking failed: r=%d\n", r); - - mxman_stop(mxman); - mxman->mxman_state = MXMAN_STATE_STOPPED; - mutex_unlock(&mxman->mxman_mutex); - } else if (mxman->mxman_state == MXMAN_STATE_FAILED) { - if (WARN_ON(!mxman->users)) - SCSC_TAG_ERR(MXMAN, "ERROR users=%d\n", mxman->users); - - mxman->users--; - if (mxman->users) { - SCSC_TAG_INFO(MXMAN, "Current number of users=%d\n", mxman->users); - mutex_unlock(&mxman->mxman_mutex); - return; - } -#ifdef CONFIG_SCSC_MXLOGGER -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Unregister minimoredump client */ - scsc_log_collector_unregister_client(&mini_moredump_client); -#endif - /** - * Deinit mxlogger on last service stop...BUT before asking for HALT - */ - mxlogger_deinit(mxman->mx, scsc_mx_get_mxlogger(mxman->mx)); -#endif - - mxman_stop(mxman); - mxman->mxman_state = MXMAN_STATE_STOPPED; - mutex_unlock(&mxman->mxman_mutex); - complete(&mxman->recovery_completion); - } else { - WARN_ON(mxman->mxman_state != MXMAN_STATE_STARTED); - SCSC_TAG_ERR(MXMAN, "Bad state: mxman->mxman_state=%d\n", mxman->mxman_state); - mutex_unlock(&mxman->mxman_mutex); - return; - } -} - -void mxman_syserr(struct mxman *mxman, struct mx_syserr_decode *syserr) -{ - mxman->syserr_recovery_in_progress = true; - - mxman->last_syserr.subsys = syserr->subsys; - mxman->last_syserr.level = syserr->level; - mxman->last_syserr.type = syserr->type; - mxman->last_syserr.subcode = syserr->subcode; - - syserr_recovery_wq_start(mxman); -} - -void mxman_fail(struct mxman *mxman, u16 scsc_panic_code, const char *reason) -{ - SCSC_TAG_WARNING(MXMAN, "WLBT FW failure\n"); - - /* The STARTING state allows a crash during firmware boot to be handled */ - if (mxman->mxman_state == MXMAN_STATE_STARTED || mxman->mxman_state == MXMAN_STATE_STARTING) { - mxman->mxman_next_state = MXMAN_STATE_FAILED; - mxman->scsc_panic_code = scsc_panic_code; - strlcpy(mxman->failure_reason, reason, sizeof(mxman->failure_reason)); - /* If recovery is disabled, don't let it be - * re-enabled from now on. Device must reboot - */ - if (mxman_recovery_disabled()) - disable_recovery_until_reboot = true; - - failure_wq_start(mxman); - } else { - SCSC_TAG_WARNING(MXMAN, "Not in MXMAN_STATE_STARTED state, ignore (state %d)\n", mxman->mxman_state); - } - - /* Populate syserr info with panic equivalent or best we can */ - mxman->last_syserr.subsys = scsc_panic_code >> SYSERR_SUB_SYSTEM_POSN; - mxman->last_syserr.level = MX_SYSERR_LEVEL_7; - mxman->last_syserr.type = scsc_panic_code; - mxman->last_syserr.subcode = scsc_panic_code; -} - -void mxman_freeze(struct mxman *mxman) -{ - SCSC_TAG_WARNING(MXMAN, "WLBT FW frozen\n"); - - if (mxman->mxman_state == MXMAN_STATE_STARTED) { - mxman->mxman_next_state = MXMAN_STATE_FROZEN; - failure_wq_start(mxman); - } else { - SCSC_TAG_WARNING(MXMAN, "Not in MXMAN_STATE_STARTED state, ignore (state %d)\n", mxman->mxman_state); - } -} - -void mxman_init(struct mxman *mxman, struct scsc_mx *mx) -{ - mxman->mx = mx; - mxman->suspended = 0; -#ifdef CONFIG_SCSC_FM - mxman->on_halt_ldos_on = 0; - mxman->fm_params_pending = 0; -#endif - fw_crc_wq_init(mxman); - failure_wq_init(mxman); - syserr_recovery_wq_init(mxman); -#ifdef CONFIG_SCSC_WLBTD - wlbtd_wq_init(mxman); -#endif - mutex_init(&mxman->mxman_mutex); - mutex_init(&mxman->mxman_recovery_mutex); - init_completion(&mxman->recovery_completion); -#ifdef CONFIG_ANDROID - wake_lock_init(&mxman->failure_recovery_wake_lock, WAKE_LOCK_SUSPEND, "mxman_recovery"); - wake_lock_init(&mxman->syserr_recovery_wake_lock, WAKE_LOCK_SUSPEND, "mxman_syserr_recovery"); -#endif - mxman->syserr_recovery_in_progress = false; - mxman->last_syserr_recovery_time = 0; - - /* set the initial state */ - mxman->mxman_state = MXMAN_STATE_STOPPED; - (void)snprintf(mxman->fw_build_id, sizeof(mxman->fw_build_id), "unknown"); - memcpy(saved_fw_build_id, mxman->fw_build_id, - sizeof(saved_fw_build_id)); - (void)snprintf(mxman->fw_ttid, sizeof(mxman->fw_ttid), "unknown"); - mxproc_create_info_proc_dir(&mxman->mxproc, mxman); - active_mxman = mxman; - -#if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000 - mxman_create_sysfs_memdump(); -#endif - scsc_lerna_init(); -} - -void mxman_deinit(struct mxman *mxman) -{ - scsc_lerna_deinit(); -#if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000 - mxman_destroy_sysfs_memdump(); -#endif - active_mxman = NULL; - mxproc_remove_info_proc_dir(&mxman->mxproc); - fw_crc_wq_deinit(mxman); - failure_wq_deinit(mxman); - syserr_recovery_wq_deinit(mxman); -#ifdef CONFIG_SCSC_WLBTD - wlbtd_wq_deinit(mxman); -#endif -#ifdef CONFIG_ANDROID - wake_lock_destroy(&mxman->failure_recovery_wake_lock); - wake_lock_destroy(&mxman->syserr_recovery_wake_lock); -#endif - mutex_destroy(&mxman->mxman_recovery_mutex); - mutex_destroy(&mxman->mxman_mutex); -} - -int mxman_force_panic(struct mxman *mxman) -{ - struct srvman *srvman; - struct ma_msg_packet message = { .ma_msg = MM_FORCE_PANIC }; - - mutex_lock(&mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return -EINVAL; - } - - if (mxman->mxman_state == MXMAN_STATE_STARTED) { - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman->mx), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, &message, sizeof(message)); - mutex_unlock(&mxman->mxman_mutex); - return 0; - } - mutex_unlock(&mxman->mxman_mutex); - return -EINVAL; -} - -int mxman_suspend(struct mxman *mxman) -{ - struct srvman *srvman; - struct ma_msg_packet message = { .ma_msg = MM_HOST_SUSPEND }; - int ret; - - SCSC_TAG_INFO(MXMAN, "\n"); - - mutex_lock(&mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return 0; - } - - /* Call Service suspend callbacks */ - ret = srvman_suspend_services(srvman); - if (ret) { - mutex_unlock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Service Suspend canceled - ignore %d\n", ret); - return ret; - } - - if (mxman->mxman_state == MXMAN_STATE_STARTED) { - SCSC_TAG_INFO(MXMAN, "MM_HOST_SUSPEND\n"); -#ifdef CONFIG_SCSC_MXLOGGER - mxlogger_generate_sync_record(scsc_mx_get_mxlogger(mxman->mx), MXLOGGER_SYN_SUSPEND); -#endif - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman->mx), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, &message, sizeof(message)); - mxman->suspended = 1; - atomic_inc(&mxman->suspend_count); - } - mutex_unlock(&mxman->mxman_mutex); - return 0; -} - -#ifdef CONFIG_SCSC_FM -void mxman_fm_on_halt_ldos_on(void) -{ - /* Should always be an active mxman unless module is unloaded */ - if (!active_mxman) { - SCSC_TAG_ERR(MXMAN, "No active MXMAN\n"); - return; - } - - active_mxman->on_halt_ldos_on = 1; - - /* FM status to pass into FW at next FW init, - * by which time driver context is lost. - * This is required, because now WLBT gates - * LDOs with TCXO instead of leaving them - * always on, to save power in deep sleep. - * FM, however, needs them always on. So - * we need to know when to leave the LDOs - * alone at WLBT boot. - */ - is_fm_on = 1; -} - -void mxman_fm_on_halt_ldos_off(void) -{ - /* Should always be an active mxman unless module is unloaded */ - if (!active_mxman) { - SCSC_TAG_ERR(MXMAN, "No active MXMAN\n"); - return; - } - - /* Newer FW no longer need set shared LDOs - * always-off at WLBT halt, as TCXO gating - * has the same effect. But pass the "off" - * request for backwards compatibility - * with old FW. - */ - active_mxman->on_halt_ldos_on = 0; - is_fm_on = 0; -} - -/* Update parameters passed to WLBT FM */ -int mxman_fm_set_params(struct wlbt_fm_params *params) -{ - /* Should always be an active mxman unless module is unloaded */ - if (!active_mxman) { - SCSC_TAG_ERR(MXMAN, "No active MXMAN\n"); - return -EINVAL; - } - - /* Params are no longer valid (FM stopped) */ - if (!params) { - active_mxman->fm_params_pending = 0; - SCSC_TAG_INFO(MXMAN, "FM params cleared\n"); - return 0; - } - - /* Once set the value needs to be remembered for each time WLBT starts */ - active_mxman->fm_params = *params; - active_mxman->fm_params_pending = 1; - - if (send_fm_params_to_active_mxman(params)) { - SCSC_TAG_INFO(MXMAN, "FM params sent to FW\n"); - return 0; - } - - /* Stored for next time FW is up */ - SCSC_TAG_INFO(MXMAN, "FM params stored\n"); - - return -EAGAIN; -} -#endif - -void mxman_resume(struct mxman *mxman) -{ - struct srvman *srvman; - struct ma_msg_packet message = { .ma_msg = MM_HOST_RESUME }; - int ret; - - SCSC_TAG_INFO(MXMAN, "\n"); - - mutex_lock(&mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Called during error - ignore\n"); - return; - } - - if (mxman->mxman_state == MXMAN_STATE_STARTED) { - SCSC_TAG_INFO(MXMAN, "MM_HOST_RESUME\n"); -#ifdef CONFIG_SCSC_MXLOGGER - mxlogger_generate_sync_record(scsc_mx_get_mxlogger(mxman->mx), MXLOGGER_SYN_RESUME); -#endif - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman->mx), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, &message, sizeof(message)); - mxman->suspended = 0; - } - - /* Call Service Resume callbacks */ - ret = srvman_resume_services(srvman); - if (ret) - SCSC_TAG_INFO(MXMAN, "Service Resume error %d\n", ret); - - mutex_unlock(&mxman->mxman_mutex); -} - -static void _mx_exec_cleanup(struct subprocess_info *sp_info) -{ - if (!sp_info) { - SCSC_TAG_ERR(MXMAN, "sp_info is null\n"); - return; - } - if (!sp_info->argv) { - SCSC_TAG_ERR(MXMAN, "argv is null\n"); - return; - } - - SCSC_TAG_INFO(MXMAN, "0x%p\n", sp_info->argv); - argv_free(sp_info->argv); -} - -/* prog - full path to programme - * wait_exec - one of UMH_WAIT_EXEC, UMH_WAIT_PROC, UMH_KILLABLE, UMH_NO_WAIT - */ -static int _mx_exec(char *prog, int wait_exec) -{ - /** - * ENV vars ANDROID_ROOT and ANDROID_DATA are needed to have - * the UMH spawned process working properly (as an example finding - * Timezones files) - */ - static char const *envp[] = { "HOME=/", "PATH=/sbin:/system/sbin:/system/bin:/system/xbin:/vendor/bin:/vendor/xbin", - "ANDROID_ROOT=/system", "ANDROID_DATA=/data", NULL }; - char **argv; - char argv_str[STRING_BUFFER_MAX_LENGTH]; - int argc, result, len; - struct subprocess_info *sp_info; - - len = snprintf(argv_str, STRING_BUFFER_MAX_LENGTH, "%s", prog); - if (len >= STRING_BUFFER_MAX_LENGTH) { - /* snprintf() returns a value of buffer size of greater if it had to truncate the format string. */ - SCSC_TAG_ERR(MXMAN, - "exec string buffer insufficient (buffer size=%d, actual string=%d)\n", - STRING_BUFFER_MAX_LENGTH, len); - return -E2BIG; - } - - /* Kernel library function argv_split() will allocate memory for argv. */ - argc = 0; - argv = argv_split(GFP_KERNEL, argv_str, &argc); - if (!argv) { - SCSC_TAG_ERR(MXMAN, "failed to allocate argv for userspace helper\n"); - return -ENOMEM; - } - - /* Check the argument count just to avoid future abuse */ - if (argc > NUMBER_OF_STRING_ARGS) { - SCSC_TAG_ERR(MXMAN, - "exec string has the wrong number of arguments (has %d, should be %d)\n", - argc, NUMBER_OF_STRING_ARGS); - argv_free(argv); - return -E2BIG; - } - - /* Allocate sp_info and initialise pointers to argv and envp. */ - sp_info = call_usermodehelper_setup(argv[0], argv, (char **)envp, - GFP_KERNEL, NULL, _mx_exec_cleanup, - NULL); - - if (!sp_info) { - SCSC_TAG_ERR(MXMAN, "call_usermodehelper_setup() failed\n"); - argv_free(argv); - return -EIO; - } - - /* Put sp_info into work queue for processing by khelper. */ - SCSC_TAG_INFO(MXMAN, "Launch %s\n", prog); - - result = call_usermodehelper_exec(sp_info, wait_exec); - - if (result != 0) { - /* - * call_usermodehelper_exec() will free sp_info and call any cleanup function - * whether it succeeds or fails, so do not free argv. - */ - if (result == -ENOENT) - SCSC_TAG_ERR(MXMAN, "call_usermodehelper() failed with %d, Executable not found %s'\n", - result, prog); - else - SCSC_TAG_ERR(MXMAN, "call_usermodehelper_exec() failed with %d\n", result); - } - return result; -} - -#if defined(CONFIG_SCSC_PRINTK) && !defined(CONFIG_SCSC_WLBTD) -static int __stat(const char *file) -{ - struct kstat stat; - mm_segment_t fs; - int r; - - fs = get_fs(); - set_fs(get_ds()); - r = vfs_stat(file, &stat); - set_fs(fs); - - return r; -} -#endif - -int mx140_log_dump(void) -{ -#ifdef CONFIG_SCSC_PRINTK - int r; -# ifdef CONFIG_SCSC_WLBTD - r = schedule_work(&wlbtd_work); -# else - char mxlbin[128]; - - r = mx140_exe_path(NULL, mxlbin, sizeof(mxlbin), "mx_logger_dump.sh"); - if (r) { - SCSC_TAG_ERR(MXMAN, "mx_logger_dump.sh path error\n"); - } else { - /* - * Test presence of script before invoking, to suppress - * unnecessary error message if not installed. - */ - r = __stat(mxlbin); - if (r) { - SCSC_TAG_DEBUG(MXMAN, "%s not installed\n", mxlbin); - return r; - } - SCSC_TAG_INFO(MXMAN, "Invoking mx_logger_dump.sh UHM\n"); - r = _mx_exec(mxlbin, UMH_WAIT_EXEC); - if (r) - SCSC_TAG_ERR(MXMAN, "mx_logger_dump.sh err:%d\n", r); - } -# endif /* CONFIG_SCSC_WLBTD */ - return r; -#else - return 0; -#endif -} -EXPORT_SYMBOL(mx140_log_dump); - -bool mxman_recovery_disabled(void) -{ -#ifdef CONFIG_SCSC_WLBT_AUTORECOVERY_PERMANENT_DISABLE - /* Add option to kill autorecovery, ignoring module parameter - * to work around platform that enables it against our wishes - */ - SCSC_TAG_ERR(MXMAN, "CONFIG_SCSC_WLBT_AUTORECOVERY_PERMANENT_DISABLE is set\n"); - return true; -#endif - /* If FW has panicked when recovery was disabled, don't allow it to - * be enabled. The horse has bolted. - */ - if (disable_recovery_until_reboot) - return true; - - if (disable_recovery_handling == MEMDUMP_FILE_FOR_RECOVERY) - return disable_recovery_from_memdump_file; - else - return disable_recovery_handling ? true : false; -} -EXPORT_SYMBOL(mxman_recovery_disabled); - -/** - * This returns the last known loaded FW build_id - * even when the fw is NOT running at the time of the request. - * - * It could be used anytime by Android Enhanced Logging - * to query for fw version. - */ -void mxman_get_fw_version(char *version, size_t ver_sz) -{ - /* unavailable only if chip not probed ! */ - snprintf(version, ver_sz, "%s", saved_fw_build_id); -} -EXPORT_SYMBOL(mxman_get_fw_version); - -void mxman_get_driver_version(char *version, size_t ver_sz) -{ - /* IMPORTANT - Do not change the formatting as User space tooling is parsing the string - * to read SAP fapi versions. */ - snprintf(version, ver_sz, "drv_ver: %u.%u.%u.%u", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT); -#ifdef CONFIG_SCSC_WLBTD - scsc_wlbtd_get_and_print_build_type(); -#endif -} -EXPORT_SYMBOL(mxman_get_driver_version); - -int mxman_register_firmware_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&firmware_chain, nb); -} -EXPORT_SYMBOL(mxman_register_firmware_notifier); - -int mxman_unregister_firmware_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&firmware_chain, nb); -} -EXPORT_SYMBOL(mxman_unregister_firmware_notifier); - - -int mxman_lerna_send(struct mxman *mxman, void *message, u32 message_size) -{ - struct srvman *srvman = NULL; - - /* May be called when WLBT is off, so find the context in this case */ - if (!mxman) - mxman = active_mxman; - - if (!active_mxman) { - SCSC_TAG_ERR(MXMAN, "No active MXMAN\n"); - return -EINVAL; - } - - if (!message || (message_size == 0)) { - SCSC_TAG_INFO(MXMAN, "No lerna request provided.\n"); - return 0; - } - - mutex_lock(&active_mxman->mxman_mutex); - srvman = scsc_mx_get_srvman(active_mxman->mx); - if (srvman && srvman->error) { - mutex_unlock(&active_mxman->mxman_mutex); - SCSC_TAG_INFO(MXMAN, "Lerna configuration called during error - ignore\n"); - return 0; - } - - if (active_mxman->mxman_state == MXMAN_STATE_STARTED) { - SCSC_TAG_INFO(MXMAN, "MM_LERNA_CONFIG\n"); - mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman->mx), - MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT, message, - message_size); - mutex_unlock(&active_mxman->mxman_mutex); - return 0; - } - - SCSC_TAG_INFO(MXMAN, "MXMAN is NOT STARTED...cannot send MM_LERNA_CONFIG msg.\n"); - mutex_unlock(&active_mxman->mxman_mutex); - return -EAGAIN; -} diff --git a/drivers/misc/samsung/scsc/mxman.h b/drivers/misc/samsung/scsc/mxman.h deleted file mode 100755 index 0bca17a8629b..000000000000 --- a/drivers/misc/samsung/scsc/mxman.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef _MAXWELL_MANAGER_H -#define _MAXWELL_MANAGER_H -#include -#include "fwhdr.h" -#include "mxmgmt_transport.h" -#include "mxproc.h" -#include -#ifdef CONFIG_ANDROID -#include -#endif - -struct mxman; - -void mxman_init(struct mxman *mxman, struct scsc_mx *mx); -void mxman_deinit(struct mxman *mxman); -int mxman_open(struct mxman *mxman); -void mxman_close(struct mxman *mxman); -void mxman_fail(struct mxman *mxman, u16 scsc_panic_code, const char *reason); -void mxman_syserr(struct mxman *mxman, struct mx_syserr_decode *syserr); -void mxman_freeze(struct mxman *mxman); -int mxman_force_panic(struct mxman *mxman); -int mxman_suspend(struct mxman *mxman); -void mxman_resume(struct mxman *mxman); -void mxman_show_last_panic(struct mxman *mxman); -void mxman_subserv_recovery(struct mxman *mxman, struct mx_syserr_decode *syserr_decode); - -#ifdef CONFIG_SCSC_FM -void mxman_fm_on_halt_ldos_on(void); -void mxman_fm_on_halt_ldos_off(void); -int mxman_fm_set_params(struct wlbt_fm_params *params); -#endif -int mxman_lerna_send(struct mxman *mxman, void *data, u32 size); - -enum mxman_state { - MXMAN_STATE_STOPPED, - MXMAN_STATE_STARTING, - MXMAN_STATE_STARTED, - MXMAN_STATE_FAILED, - MXMAN_STATE_FROZEN, -}; - -#define SCSC_FAILURE_REASON_LEN 256 - -struct mxman { - struct scsc_mx *mx; - int users; - void *start_dram; - struct workqueue_struct *fw_crc_wq; - struct delayed_work fw_crc_work; - struct workqueue_struct *failure_wq; /* For recovery from chip restart */ - struct work_struct failure_work; /* For recovery from chip restart */ - struct workqueue_struct *syserr_recovery_wq; /* For recovery from syserr sub-system restart */ - struct work_struct syserr_recovery_work; /* For recovery from syserr sub-system restart */ - char *fw; - u32 fw_image_size; - struct completion mm_msg_start_ind_completion; - struct completion mm_msg_halt_rsp_completion; - struct fwhdr fwhdr; - struct mxconf *mxconf; - enum mxman_state mxman_state; - enum mxman_state mxman_next_state; - struct mutex mxman_mutex; - struct mutex mxman_recovery_mutex; /* Syserr sub-sytem and full chip restart co-ordination */ - struct mxproc mxproc; - int suspended; - atomic_t suspend_count; - atomic_t recovery_count; - atomic_t boot_count; - bool check_crc; - char fw_build_id[FW_BUILD_ID_SZ]; /* Defined in SC-505846-SW */ - struct completion recovery_completion; -#ifdef CONFIG_ANDROID - struct wake_lock failure_recovery_wake_lock; /* For recovery from chip restart */ - struct wake_lock syserr_recovery_wake_lock; /* For recovery from syserr sub-system restart */ -#endif - u32 rf_hw_ver; - u16 scsc_panic_code; - u64 last_panic_time; - u32 last_panic_rec_r[PANIC_RECORD_SIZE]; /* Must be at least SCSC_R4_V2_MINOR_53 */ - u16 last_panic_rec_sz; - struct mx_syserr_decode last_syserr; - unsigned long last_syserr_recovery_time; /* In jiffies */ - bool notify; - bool syserr_recovery_in_progress; -#ifdef CONFIG_SCSC_FM - u32 on_halt_ldos_on; -#endif - char failure_reason[SCSC_FAILURE_REASON_LEN]; /* previous failure reason */ - struct wlbt_fm_params fm_params; /* FM freq info */ - int fm_params_pending; /* FM freq info waiting to be delivered to FW */ - - char fw_ttid[FW_TTID_SZ]; /* Defined in SC-505846-SW */ -}; - -void mxman_register_gdb_channel(struct scsc_mx *mx, mxmgmt_channel_handler handler, void *data); -void mxman_send_gdb_channel(struct scsc_mx *mx, void *data, size_t length); - -#ifdef CONFIG_SCSC_CHV_SUPPORT -#define SCSC_CHV_ARGV_ADDR_OFFSET 0x200008 - -extern int chv_run; -#endif - -#define SCSC_SYSERR_HOST_SERVICE_SHIFT 4 - -#endif diff --git a/drivers/misc/samsung/scsc/mxmgmt_transport.c b/drivers/misc/samsung/scsc/mxmgmt_transport.c deleted file mode 100644 index ec4f95c82b8f..000000000000 --- a/drivers/misc/samsung/scsc/mxmgmt_transport.c +++ /dev/null @@ -1,302 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * Maxwell management transport (implementation) - */ - -/** Implements */ -#include "mxmgmt_transport.h" - -/** Uses */ -#include -#include -#include "mxmgmt_transport_format.h" -#include "mifintrbit.h" - -/* Flag that an error has occurred so the I/O thread processing should stop */ -void mxmgmt_transport_set_error(struct mxmgmt_transport *mxmgmt_transport) -{ - SCSC_TAG_WARNING(MXMGT_TRANS, "I/O thread processing is suspended\n"); - - mxmgmt_transport->mxmgmt_thread.block_thread = 1; -} - -/** MIF Interrupt handler for writes made to the AP */ -static void input_irq_handler(int irq, void *data) -{ - struct mxmgmt_transport *mxmgmt_transport = (struct mxmgmt_transport *)data; - struct mxmgmt_thread *th = &mxmgmt_transport->mxmgmt_thread; - struct scsc_mif_abs *mif_abs; - - SCSC_TAG_DEBUG(MXMGT_TRANS, "IN\n"); - /* Clear the interrupt first to ensure we can't possibly miss one */ - mif_abs = scsc_mx_get_mif_abs(mxmgmt_transport->mx); - mif_abs->irq_bit_clear(mif_abs, irq); - - /* The the other side wrote some data to the input stream, wake up the thread - * that deals with this. */ - if (th->task == NULL) { - SCSC_TAG_ERR(MXMGT_TRANS, "th is NOT running\n"); - return; - } - /* - * If an error has occured, we discard silently all messages from the stream - * until the error has been processed and the system has been reinitialised. - */ - if (th->block_thread == 1) { - SCSC_TAG_DEBUG(MXMGT_TRANS, "discard message.\n"); - /* - * Do not try to acknowledge a pending interrupt here. - * This function is called by a function which in turn can be - * running in an atomic or 'disabled irq' level. - */ - return; - } - th->wakeup_flag = 1; - - /* wake up I/O thread */ - wake_up_interruptible(&th->wakeup_q); -} - -/** MIF Interrupt handler for acknowledging writes made by the AP */ -static void output_irq_handler(int irq, void *data) -{ - struct scsc_mif_abs *mif_abs; - struct mxmgmt_transport *mxmgmt_transport = (struct mxmgmt_transport *)data; - - SCSC_TAG_DEBUG(MXMGT_TRANS, "OUT\n"); - - /* Clear the interrupt first to ensure we can't possibly miss one */ - /* The FW read some data from the output stream. - * Currently we do not care, so just clear the interrupt. */ - mif_abs = scsc_mx_get_mif_abs(mxmgmt_transport->mx); - mif_abs->irq_bit_clear(mif_abs, irq); - - /* The driver doesn't use the ack IRQ, so mask it from now on, - * otherwise we may get spurious host-wakes. - */ - mif_abs->irq_bit_mask(mif_abs, irq); -} - - -static void thread_wait_until_stopped(struct mxmgmt_transport *mxmgmt_transport) -{ - struct mxmgmt_thread *th = &mxmgmt_transport->mxmgmt_thread; - - /* - * kthread_stop() cannot handle the th exiting while - * kthread_should_stop() is false, so sleep until kthread_stop() - * wakes us up. - */ - SCSC_TAG_DEBUG(MXMGT_TRANS, "%s waiting for the stop signal.\n", th->name); - set_current_state(TASK_INTERRUPTIBLE); - if (!kthread_should_stop()) { - SCSC_TAG_DEBUG(MXMGT_TRANS, "%s schedule....\n", th->name); - schedule(); - } - - th->task = NULL; - SCSC_TAG_DEBUG(MXMGT_TRANS, "%s exiting....\n", th->name); -} - -/** - * A thread that forwards messages sent across the transport to - * the registered handlers for each channel. - */ -static int mxmgmt_thread_function(void *arg) -{ - struct mxmgmt_transport *mxmgmt_transport = (struct mxmgmt_transport *)arg; - struct mxmgmt_thread *th = &mxmgmt_transport->mxmgmt_thread; - const struct mxmgr_message *current_message; - int ret; - - complete(&th->completion); - - th->block_thread = 0; - while (!kthread_should_stop()) { - /* wait until an error occurs, or we need to process something. */ - - ret = wait_event_interruptible(th->wakeup_q, - (th->wakeup_flag && !th->block_thread) || - kthread_should_stop()); - - if (kthread_should_stop()) { - SCSC_TAG_DEBUG(MXMGT_TRANS, "signalled to exit\n"); - break; - } - if (ret < 0) { - SCSC_TAG_DEBUG(MXMGT_TRANS, "wait_event returned %d, thread will exit\n", ret); - thread_wait_until_stopped(mxmgmt_transport); - break; - } - th->wakeup_flag = 0; - SCSC_TAG_DEBUG(MXMGT_TRANS, "wokeup: r=%d\n", ret); - /* Forward each pending message to the applicable channel handler */ - current_message = mif_stream_peek(&mxmgmt_transport->mif_istream, NULL); - while (current_message != NULL) { - mutex_lock(&mxmgmt_transport->channel_handler_mutex); - if (current_message->channel_id < MMTRANS_NUM_CHANNELS && - mxmgmt_transport->channel_handler_fns[current_message->channel_id]) { - SCSC_TAG_DEBUG(MXMGT_TRANS, "Calling handler for channel_id: %d\n", current_message->channel_id); - (*mxmgmt_transport->channel_handler_fns[current_message->channel_id])(current_message->payload, - mxmgmt_transport->channel_handler_data[current_message->channel_id]); - } else - /* HERE: Invalid channel or no handler, raise fault or log message */ - SCSC_TAG_WARNING(MXMGT_TRANS, "Invalid channel or no handler channel_id: %d\n", current_message->channel_id); - mutex_unlock(&mxmgmt_transport->channel_handler_mutex); - /* Remove the current message from the buffer before processing the next - * one in case it generated another message, otherwise it's possible we - * could run out of space in the stream before we get through all the messages. */ - mif_stream_peek_complete(&mxmgmt_transport->mif_istream, current_message); - current_message = mif_stream_peek(&mxmgmt_transport->mif_istream, NULL); - } - } - - SCSC_TAG_DEBUG(MXMGT_TRANS, "exiting....\n"); - complete(&th->completion); - return 0; -} - - -static int mxmgmt_thread_start(struct mxmgmt_transport *mxmgmt_transport) -{ - int err; - struct mxmgmt_thread *th = &mxmgmt_transport->mxmgmt_thread; - - if (th->task != NULL) { - SCSC_TAG_WARNING(MXMGT_TRANS, "%s thread already started\n", th->name); - return 0; - } - - /* Initialise thread structure */ - th->block_thread = 1; - init_waitqueue_head(&th->wakeup_q); - init_completion(&th->completion); - th->wakeup_flag = 0; - snprintf(th->name, MXMGMT_THREAD_NAME_MAX_LENGTH, "mxmgmt_thread"); - - /* Start the kernel thread */ - th->task = kthread_run(mxmgmt_thread_function, mxmgmt_transport, "%s", th->name); - if (IS_ERR(th->task)) { - SCSC_TAG_ERR(MXMGT_TRANS, "error creating kthread\n"); - return (int)PTR_ERR(th->task); - } - - SCSC_TAG_DEBUG(MXMGT_TRANS, "Started thread %s\n", th->name); - - /* wait until thread is started */ -#define MGMT_THREAD_START_TMO_SEC (3) - err = wait_for_completion_timeout(&th->completion, msecs_to_jiffies(MGMT_THREAD_START_TMO_SEC*1000)); - if (err == 0) { - SCSC_TAG_ERR(MXMGT_TRANS, "timeout in starting thread\n"); - return -ETIMEDOUT; - } - return 0; -} - -static void mgmt_thread_stop(struct mxmgmt_transport *mxmgmt_transport) -{ - unsigned long left_jiffies; - struct mxmgmt_thread *th = &mxmgmt_transport->mxmgmt_thread; - - if (!th->task) { - SCSC_TAG_WARNING(MXMGT_TRANS, "%s mgmt_thread is already stopped\n", th->name); - return; - } - SCSC_TAG_DEBUG(MXMGT_TRANS, "Stopping %s mgmt_thread\n", th->name); - kthread_stop(th->task); - /* wait until th stopped */ -#define MGMT_THREAD_STOP_TMO_SEC (3) - left_jiffies = - wait_for_completion_timeout(&th->completion, msecs_to_jiffies(MGMT_THREAD_STOP_TMO_SEC*1000)); - if (!left_jiffies) - SCSC_TAG_ERR(MXMGT_TRANS, "Failed to stop mgmt_thread %s\n", - th->name); - else - th->task = NULL; -} - -void mxmgmt_transport_release(struct mxmgmt_transport *mxmgmt_transport) -{ - mgmt_thread_stop(mxmgmt_transport); - mif_stream_release(&mxmgmt_transport->mif_istream); - mif_stream_release(&mxmgmt_transport->mif_ostream); -} - -void mxmgmt_transport_config_serialise(struct mxmgmt_transport *mxmgmt_transport, - struct mxtransconf *trans_conf) -{ - mif_stream_config_serialise(&mxmgmt_transport->mif_istream, &trans_conf->to_ap_stream_conf); - mif_stream_config_serialise(&mxmgmt_transport->mif_ostream, &trans_conf->from_ap_stream_conf); -} - - -/** Public functions */ -int mxmgmt_transport_init(struct mxmgmt_transport *mxmgmt_transport, struct scsc_mx *mx) -{ -#define MEM_LENGTH 512 - int r; - uint32_t mem_length = MEM_LENGTH; - uint32_t packet_size = sizeof(struct mxmgr_message); - uint32_t num_packets; - - - /* - * Initialising a buffer of 1 byte is never legitimate, do not allow it. - * The memory buffer length must be a multiple of the packet size. - */ - if (mem_length <= 1 || mem_length % packet_size != 0) - return -EIO; - memset(mxmgmt_transport, 0, sizeof(struct mxmgmt_transport)); - num_packets = mem_length / packet_size; - mutex_init(&mxmgmt_transport->channel_handler_mutex); - mxmgmt_transport->mx = mx; - r = mif_stream_init(&mxmgmt_transport->mif_istream, SCSC_MIF_ABS_TARGET_R4, MIF_STREAM_DIRECTION_IN, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_ALLOC, input_irq_handler, mxmgmt_transport); - if (r) { - SCSC_TAG_ERR(MXMGT_TRANS, "mif_stream_init IN failed %d\n", r); - return r; - } - r = mif_stream_init(&mxmgmt_transport->mif_ostream, SCSC_MIF_ABS_TARGET_R4, MIF_STREAM_DIRECTION_OUT, num_packets, packet_size, mx, MIF_STREAM_INTRBIT_TYPE_ALLOC, output_irq_handler, mxmgmt_transport); - if (r) { - SCSC_TAG_ERR(MXMGT_TRANS, "mif_stream_init OUT failed %d\n", r); - mif_stream_release(&mxmgmt_transport->mif_istream); - return r; - } - - r = mxmgmt_thread_start(mxmgmt_transport); - if (r) { - SCSC_TAG_ERR(MXMGT_TRANS, "mxmgmt_thread_start failed %d\n", r); - mif_stream_release(&mxmgmt_transport->mif_istream); - mif_stream_release(&mxmgmt_transport->mif_ostream); - return r; - } - return 0; -} - -void mxmgmt_transport_register_channel_handler(struct mxmgmt_transport *mxmgmt_transport, enum mxmgr_channels channel_id, - mxmgmt_channel_handler handler, void *data) -{ - if (channel_id >= MMTRANS_NUM_CHANNELS) { - SCSC_TAG_ERR(MXMGT_TRANS, "Invalid channel id: %d\n", channel_id); - return; - } - mutex_lock(&mxmgmt_transport->channel_handler_mutex); - mxmgmt_transport->channel_handler_fns[channel_id] = handler; - mxmgmt_transport->channel_handler_data[channel_id] = data; - mutex_unlock(&mxmgmt_transport->channel_handler_mutex); -} - -void mxmgmt_transport_send(struct mxmgmt_transport *mxmgmt_transport, enum mxmgr_channels channel_id, - void *message, uint32_t message_length) -{ - struct mxmgr_message transport_msg = { .channel_id = channel_id }; - - const void *bufs[2] = { &transport_msg.channel_id, message }; - uint32_t buf_lengths[2] = { sizeof(transport_msg.channel_id), message_length }; - - mif_stream_write_gather(&mxmgmt_transport->mif_ostream, bufs, buf_lengths, 2); -} diff --git a/drivers/misc/samsung/scsc/mxmgmt_transport.h b/drivers/misc/samsung/scsc/mxmgmt_transport.h deleted file mode 100644 index 36039bd54495..000000000000 --- a/drivers/misc/samsung/scsc/mxmgmt_transport.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/** - * mx140 management transport (Interface) - * - * Provides bi-directional communication between the firmware and the - * host. Messages sent across the transport are divided into a - * number of channels, with each channel having its own dedicated handler. - * - * This interface also provides a utility method for sending messages across - * the stream. - */ - -#ifndef MXMANAGEMENT_TRANSPORT_H__ -#define MXMANAGEMENT_TRANSPORT_H__ - -/** Uses */ -#include -#include "mifstream.h" - -struct mxmgmt_transport; - -/** - * The various channels that can send messages - * across the transport. - * - * Channel IDs are limited to one byte. - */ -enum mxmgr_channels { - MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT = 0, - MMTRANS_CHAN_ID_SERVICE_MANAGEMENT = 1, - MMTRANS_CHAN_ID_MAXWELL_LOGGING = 2, - MMTRANS_NUM_CHANNELS = 3 -}; - -/** - * Transport channel callback handler. This will be invoked each time a message on a channel is - * received in the context of the transport stream's thread. Handlers may perform work within - * their callback implementation, but should not block. - * - * Note that the message pointer passed is only valid for the duration of the function call. - */ -typedef void (*mxmgmt_channel_handler)(const void *message, void *data); - -/** - * Registers the callback function that will be invoked to handle data coming in from the AP - * for the given channel. - */ -void mxmgmt_transport_register_channel_handler(struct mxmgmt_transport *mxmgmt_transport, enum mxmgr_channels channel_id, - mxmgmt_channel_handler handler, void *data); - -/** - * Sends a message to the AP across the given channel. - * - * This function is safe to call from any RTOS thread. - */ -void mxmgmt_transport_send(struct mxmgmt_transport *mxmgmt_transport, enum mxmgr_channels channel_id, - void *message, uint32_t message_length); - -/** - * Initialises the maxwell management transport and configures the necessary - * interrupt handlers. Called once during boot. - */ -int mxmgmt_transport_init(struct mxmgmt_transport *mxmgmt_transport, struct scsc_mx *mx); -void mxmgmt_transport_release(struct mxmgmt_transport *mxmgmt_transport); - -/* - * Initialises the configuration area incl. Maxwell Infrastructure Configuration, - * MIF Management Transport Configuration and MIF Management Stream Configuration. - */ -void mxmgmt_transport_config_serialise(struct mxmgmt_transport *mxmgmt_transport, struct mxtransconf *trans_conf); -void mxmgmt_transport_set_error(struct mxmgmt_transport *mxmgmt_transport); - -#define MXMGMT_THREAD_NAME_MAX_LENGTH 32 -struct mxmgmt_thread { - struct task_struct *task; - char name[MXMGMT_THREAD_NAME_MAX_LENGTH]; - int prio; - struct completion completion; - wait_queue_head_t wakeup_q; - unsigned int wakeup_flag; - /* - * Use it to block the I/O thread when - * an error occurs. - */ - int block_thread; -}; - -struct mxmgmt_transport { - struct scsc_mx *mx; - struct mif_stream mif_istream; - struct mif_stream mif_ostream; - struct mxmgmt_thread mxmgmt_thread; - /** Registered channel handlers for messages coming from the AP for each channel */ - mxmgmt_channel_handler channel_handler_fns[MMTRANS_NUM_CHANNELS]; - void *channel_handler_data[MMTRANS_NUM_CHANNELS]; - struct mutex channel_handler_mutex; -}; - -#endif /* MXMANAGEMENT_TRANSPORT_H__ */ diff --git a/drivers/misc/samsung/scsc/mxmgmt_transport_format.h b/drivers/misc/samsung/scsc/mxmgmt_transport_format.h deleted file mode 100644 index 291faca9b644..000000000000 --- a/drivers/misc/samsung/scsc/mxmgmt_transport_format.h +++ /dev/null @@ -1,23 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef MXMGR_TRANSPORT_FORMAT_H__ -#define MXMGR_TRANSPORT_FORMAT_H__ - -#define MXMGR_MESSAGE_PAYLOAD_SIZE 127 - -/** - * Layout of messages across the manager transport streams. - * - * HERE: This is a dummy definition and will be replaced - * once more of the service management infrastructure is completed. - */ -struct mxmgr_message { - uint8_t channel_id; /* Channel ID from mxmgr_channels */ - uint8_t payload[MXMGR_MESSAGE_PAYLOAD_SIZE]; /* Message content to store in the transport stream - user defined format */ -} __packed; - -#endif /* MXMGR_TRANSPORT_FORMAT_H__ */ diff --git a/drivers/misc/samsung/scsc/mxmgmt_transport_streams.h b/drivers/misc/samsung/scsc/mxmgmt_transport_streams.h deleted file mode 100644 index e906003c2616..000000000000 --- a/drivers/misc/samsung/scsc/mxmgmt_transport_streams.h +++ /dev/null @@ -1,24 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef MXMGR_TRANSPORT_STREAMS_H__ -#define MXMGR_TRANSPORT_STREAMS_H__ - -/** - * MIF input/output streams to/from the AP. - * These are seperated out to allow their use directly from within unit tests. - */ -struct { - /** from AP */ - mif_stream *istream; - /** to AP */ - mif_stream *ostream; -} mxmgr_stream_container; - -extern mxmgr_stream_container mxmgr_streams; - - -#endif /* MXMGR_TRANSPORT_STREAMS_H__ */ diff --git a/drivers/misc/samsung/scsc/mxproc.c b/drivers/misc/samsung/scsc/mxproc.c deleted file mode 100644 index 5d5d76c3135c..000000000000 --- a/drivers/misc/samsung/scsc/mxproc.c +++ /dev/null @@ -1,585 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include "mxman.h" -#include "mxproc.h" -#ifdef CONFIG_SCSC_WLBTD -#include "scsc_wlbtd.h" -#endif - -#ifndef AID_MXPROC -#define AID_MXPROC 0 -#endif - -#define MX_PROCFS_RW_FILE_OPS(name) \ - static ssize_t mx_procfs_ ## name ## _write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); \ - static ssize_t mx_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations mx_procfs_ ## name ## _fops = { \ - .read = mx_procfs_ ## name ## _read, \ - .write = mx_procfs_ ## name ## _write, \ - .open = mx_procfs_generic_open, \ - .llseek = generic_file_llseek \ - } -#define MX_PROCFS_RO_FILE_OPS(name) \ - static ssize_t mx_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations mx_procfs_ ## name ## _fops = { \ - .read = mx_procfs_ ## name ## _read, \ - .open = mx_procfs_generic_open, \ - .llseek = generic_file_llseek \ - } - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MX_PDE_DATA(inode) PDE_DATA(inode) -#else -#define MX_PDE_DATA(inode) (PDE(inode)->data) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MX_PROCFS_SET_UID_GID(_entry) \ - do { \ - kuid_t proc_kuid = KUIDT_INIT(AID_MXPROC); \ - kgid_t proc_kgid = KGIDT_INIT(AID_MXPROC); \ - proc_set_user(_entry, proc_kuid, proc_kgid); \ - } while (0) -#else -#define MX_PROCFS_SET_UID_GID(entry) \ - do { \ - (entry)->uid = AID_MXPROC; \ - (entry)->gid = AID_MXPROC; \ - } while (0) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define MX_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry = proc_create_data(# name, mode, parent, &mx_procfs_ ## name ## _fops, _sdev); \ - MX_PROCFS_SET_UID_GID(entry); \ - } while (0) -#else -#define MX_PROCFS_ADD_FILE(_data, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = create_proc_entry(# name, mode, parent); \ - if (entry) { \ - entry->proc_fops = &mx_procfs_ ## name ## _fops; \ - entry->data = _data; \ - MX_PROCFS_SET_UID_GID(entry); \ - } \ - } while (0) -#endif - -#define MX_PROCFS_REMOVE_FILE(name, parent) remove_proc_entry(# name, parent) - -#define OS_UNUSED_PARAMETER(x) ((void)(x)) -#define MX_DIRLEN 128 -static const char *procdir_ctrl = "driver/mxman_ctrl"; -static const char *procdir_info = "driver/mxman_info"; - -static int mx_procfs_generic_open(struct inode *inode, struct file *file) -{ - file->private_data = MX_PDE_DATA(inode); - return 0; -} - -static ssize_t mx_procfs_mx_fail_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - - OS_UNUSED_PARAMETER(mxproc); - OS_UNUSED_PARAMETER(file); - OS_UNUSED_PARAMETER(user_buf); - OS_UNUSED_PARAMETER(count); - OS_UNUSED_PARAMETER(ppos); - - SCSC_TAG_DEBUG(MX_PROC, "OK\n"); - return 0; -} - -static ssize_t mx_procfs_mx_fail_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - - OS_UNUSED_PARAMETER(file); - OS_UNUSED_PARAMETER(user_buf); - OS_UNUSED_PARAMETER(count); - OS_UNUSED_PARAMETER(ppos); - - if (mxproc) - mxman_fail(mxproc->mxman, SCSC_PANIC_CODE_HOST << 15, __func__); - SCSC_TAG_DEBUG(MX_PROC, "OK\n"); - - return count; -} - -static ssize_t mx_procfs_mx_freeze_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - - OS_UNUSED_PARAMETER(mxproc); - OS_UNUSED_PARAMETER(file); - OS_UNUSED_PARAMETER(user_buf); - OS_UNUSED_PARAMETER(count); - OS_UNUSED_PARAMETER(ppos); - - SCSC_TAG_DEBUG(MX_PROC, "OK\n"); - return 0; -} - -static ssize_t mx_procfs_mx_freeze_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - - OS_UNUSED_PARAMETER(file); - OS_UNUSED_PARAMETER(user_buf); - OS_UNUSED_PARAMETER(count); - OS_UNUSED_PARAMETER(ppos); - - if (mxproc) - mxman_freeze(mxproc->mxman); - SCSC_TAG_INFO(MX_PROC, "OK\n"); - - return count; -} - -static ssize_t mx_procfs_mx_panic_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - - OS_UNUSED_PARAMETER(mxproc); - OS_UNUSED_PARAMETER(file); - OS_UNUSED_PARAMETER(user_buf); - OS_UNUSED_PARAMETER(count); - OS_UNUSED_PARAMETER(ppos); - - /* Force a FW panic on read as well as write to allow test in user builds */ - if (mxproc) - mxman_force_panic(mxproc->mxman); - SCSC_TAG_INFO(MX_PROC, "OK\n"); - - return 0; -} - -static ssize_t mx_procfs_mx_panic_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - - OS_UNUSED_PARAMETER(file); - OS_UNUSED_PARAMETER(user_buf); - OS_UNUSED_PARAMETER(count); - OS_UNUSED_PARAMETER(ppos); - - if (mxproc) - mxman_force_panic(mxproc->mxman); - SCSC_TAG_INFO(MX_PROC, "OK\n"); - - return count; -} - -static ssize_t mx_procfs_mx_lastpanic_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - char buf[64]; - int bytes; - - if (!mxproc || !mxproc->mxman) - return -EINVAL; - - memset(buf, '\0', sizeof(buf)); - - bytes = snprintf(buf, sizeof(buf), "scsc_panic_code : 0x%x\nscsc_panic_subcode : 0x%x\n", - (mxproc->mxman->scsc_panic_code), (mxproc->mxman->scsc_panic_code & 0x7FFF)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, bytes); -} - -static ssize_t mx_procfs_mx_suspend_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - char buf[3]; - - OS_UNUSED_PARAMETER(file); - - buf[0] = mxproc->mxman->suspended ? 'Y' : 'N'; - buf[1] = '\n'; - buf[2] = '\0'; - - SCSC_TAG_INFO(MX_PROC, "suspended: %c\n", buf[0]); - - return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); -} - -static ssize_t mx_procfs_mx_suspend_count_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - int pos = 0; - char buf[32]; - const size_t bufsz = sizeof(buf); - u32 suspend_count; - - OS_UNUSED_PARAMETER(file); - - if (!mxproc || !mxproc->mxman) - return 0; - - suspend_count = atomic_read(&mxproc->mxman->suspend_count); - SCSC_TAG_INFO(MX_PROC, "suspend_count: %u\n", suspend_count); - pos += scnprintf(buf + pos, bufsz - pos, "%u\n", suspend_count); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t mx_procfs_mx_recovery_count_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - int pos = 0; - char buf[32]; - const size_t bufsz = sizeof(buf); - u32 recovery_count; - - OS_UNUSED_PARAMETER(file); - - if (!mxproc || !mxproc->mxman) - return 0; - - recovery_count = atomic_read(&mxproc->mxman->recovery_count); - SCSC_TAG_INFO(MX_PROC, "recovery_count: %u\n", recovery_count); - pos += scnprintf(buf + pos, bufsz - pos, "%u\n", recovery_count); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t mx_procfs_mx_boot_count_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - int pos = 0; - char buf[32]; - const size_t bufsz = sizeof(buf); - u32 boot_count; - - OS_UNUSED_PARAMETER(file); - - if (!mxproc || !mxproc->mxman) - return 0; - - boot_count = atomic_read(&mxproc->mxman->boot_count); - SCSC_TAG_INFO(MX_PROC, "boot_count: %u\n", boot_count); - pos += scnprintf(buf + pos, bufsz - pos, "%u\n", boot_count); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t mx_procfs_mx_suspend_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - int r; - - OS_UNUSED_PARAMETER(file); - OS_UNUSED_PARAMETER(ppos); - - if (count && mxproc) { - switch (user_buf[0]) { - case 'Y': - SCSC_TAG_INFO(MX_PROC, "force suspend\n"); - r = mxman_suspend(mxproc->mxman); - if (r) { - SCSC_TAG_INFO(MX_PROC, "mx_suspend failed %d\n", r); - return r; - } - break; - case 'N': - SCSC_TAG_INFO(MX_PROC, "force resume\n"); - mxman_resume(mxproc->mxman); - break; - default: - SCSC_TAG_INFO(MX_PROC, "invalid value %c\n", user_buf[0]); - return -EINVAL; - } - } - - return count; -} - -static ssize_t mx_procfs_mx_status_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - char buf[32]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - if (!mxproc || !mxproc->mxman) - return 0; - - switch (mxproc->mxman->mxman_state) { - case MXMAN_STATE_STOPPED: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "MXMAN_STATE_STOPPED"); - break; - case MXMAN_STATE_STARTING: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "MXMAN_STATE_STARTING"); - break; - case MXMAN_STATE_STARTED: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "MXMAN_STATE_STARTED"); - break; - case MXMAN_STATE_FAILED: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "MXMAN_STATE_FAILED"); - break; - case MXMAN_STATE_FROZEN: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "MXMAN_STATE_FROZEN"); - break; - default: - return 0; - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t mx_procfs_mx_services_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - if (!mxproc || !mxproc->mxman) - return 0; - - pos = scsc_mx_list_services(mxproc->mxman, buf, bufsz); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t mx_procfs_mx_wlbt_stat_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct mxproc *mxproc = file->private_data; - struct scsc_mif_abs *mif_abs; - int pos = 0; - int r; - char buf[32]; - const size_t bufsz = sizeof(buf); - u32 val = 0xff; - - OS_UNUSED_PARAMETER(file); - - if (!mxproc || !mxproc->mxman || !mxproc->mxman->mx) - return 0; - - mif_abs = scsc_mx_get_mif_abs(mxproc->mxman->mx); - - /* Read WLBT_STAT register */ - if (mif_abs->mif_read_register) { - r = mif_abs->mif_read_register(mif_abs, SCSC_REG_READ_WLBT_STAT, &val); - if (r) - val = 0xff; /* failed */ - } - - pos += scnprintf(buf + pos, bufsz - pos, "0x%x\n", val); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -MX_PROCFS_RW_FILE_OPS(mx_fail); -MX_PROCFS_RW_FILE_OPS(mx_freeze); -MX_PROCFS_RW_FILE_OPS(mx_panic); -MX_PROCFS_RW_FILE_OPS(mx_suspend); -MX_PROCFS_RO_FILE_OPS(mx_suspend_count); -MX_PROCFS_RO_FILE_OPS(mx_recovery_count); -MX_PROCFS_RO_FILE_OPS(mx_boot_count); -MX_PROCFS_RO_FILE_OPS(mx_status); -MX_PROCFS_RO_FILE_OPS(mx_services); -MX_PROCFS_RO_FILE_OPS(mx_lastpanic); -MX_PROCFS_RO_FILE_OPS(mx_wlbt_stat); - -static u32 proc_count; - -int mxproc_create_ctrl_proc_dir(struct mxproc *mxproc, struct mxman *mxman) -{ - char dir[MX_DIRLEN]; - struct proc_dir_entry *parent; - - (void)snprintf(dir, sizeof(dir), "%s%d", procdir_ctrl, proc_count); - parent = proc_mkdir(dir, NULL); - if (!parent) { - SCSC_TAG_ERR(MX_PROC, "failed to create proc dir %s\n", procdir_ctrl); - return -EINVAL; - } -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = mxproc; -#endif - mxproc->mxman = mxman; - mxproc->procfs_ctrl_dir = parent; - mxproc->procfs_ctrl_dir_num = proc_count; - MX_PROCFS_ADD_FILE(mxproc, mx_fail, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_freeze, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_panic, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_suspend, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_suspend_count, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_recovery_count, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_status, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_services, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_lastpanic, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_wlbt_stat, parent, S_IRUSR | S_IRGRP | S_IROTH); - - SCSC_TAG_DEBUG(MX_PROC, "created %s proc dir\n", dir); - proc_count++; - - return 0; -} - -void mxproc_remove_ctrl_proc_dir(struct mxproc *mxproc) -{ - if (mxproc->procfs_ctrl_dir) { - char dir[MX_DIRLEN]; - - MX_PROCFS_REMOVE_FILE(mx_fail, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_freeze, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_panic, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_suspend, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_suspend_count, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_recovery_count, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_status, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_services, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_lastpanic, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_wlbt_stat, mxproc->procfs_ctrl_dir); - (void)snprintf(dir, sizeof(dir), "%s%d", procdir_ctrl, mxproc->procfs_ctrl_dir_num); - remove_proc_entry(dir, NULL); - mxproc->procfs_ctrl_dir = NULL; - proc_count--; - SCSC_TAG_DEBUG(MX_PROC, "removed %s proc dir\n", dir); - } -} - -static ssize_t mx_procfs_mx_rf_hw_ver_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[256]; - int bytes; - struct mxproc *mxproc = file->private_data; - - if (!mxproc || !mxproc->mxman) - return -EINVAL; - - memset(buf, '\0', sizeof(buf)); - bytes = snprintf(buf, sizeof(buf), "RF version: 0x%04x\n", (mxproc->mxman->rf_hw_ver)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, bytes); -} - -MX_PROCFS_RO_FILE_OPS(mx_rf_hw_ver); - -static ssize_t mx_procfs_mx_rf_hw_name_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[256]; - int bytes; - struct mxproc *mxproc = file->private_data; - - if (!mxproc || !mxproc->mxman) - return -EINVAL; - - memset(buf, '\0', sizeof(buf)); - - bytes = mxman_print_rf_hw_version(mxproc->mxman, buf, sizeof(buf)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, bytes); -} - -MX_PROCFS_RO_FILE_OPS(mx_rf_hw_name); - -static ssize_t mx_procfs_mx_release_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[256]; - int bytes; - struct mxproc *mxproc = file->private_data; - char *build_id = 0; - - OS_UNUSED_PARAMETER(file); - - if (mxproc && mxproc->mxman) - build_id = mxproc->mxman->fw_build_id; - - memset(buf, '\0', sizeof(buf)); - - bytes = snprintf(buf, sizeof(buf), "Release: %d.%d.%d.%d (f/w: %s)\n", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT, - build_id ? build_id : "unknown"); - - if (bytes > sizeof(buf)) - bytes = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, bytes); -} - -MX_PROCFS_RO_FILE_OPS(mx_release); - -static ssize_t mx_procfs_mx_ttid_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[256]; - int bytes; - struct mxproc *mxproc = file->private_data; - char *id = 0; - - OS_UNUSED_PARAMETER(file); - - if (mxproc && mxproc->mxman) - id = mxproc->mxman->fw_ttid; - - memset(buf, '\0', sizeof(buf)); - - bytes = snprintf(buf, sizeof(buf), "%s\n", id); - - if (bytes > sizeof(buf)) - bytes = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, bytes); -} - -MX_PROCFS_RO_FILE_OPS(mx_ttid); - -int mxproc_create_info_proc_dir(struct mxproc *mxproc, struct mxman *mxman) -{ - char dir[MX_DIRLEN]; - struct proc_dir_entry *parent; - - (void)snprintf(dir, sizeof(dir), "%s", procdir_info); - parent = proc_mkdir(dir, NULL); - if (!parent) { - SCSC_TAG_ERR(MX_PROC, "failed to create /proc dir\n"); - return -EINVAL; - } -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = mxproc; -#endif - mxproc->mxman = mxman; - mxproc->procfs_info_dir = parent; - MX_PROCFS_ADD_FILE(mxproc, mx_release, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_rf_hw_ver, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_rf_hw_name, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_boot_count, parent, S_IRUSR | S_IRGRP | S_IROTH); - MX_PROCFS_ADD_FILE(mxproc, mx_ttid, parent, S_IRUSR | S_IRGRP | S_IROTH); - SCSC_TAG_DEBUG(MX_PROC, "created %s proc dir\n", dir); - - return 0; -} - -void mxproc_remove_info_proc_dir(struct mxproc *mxproc) -{ - if (mxproc->procfs_info_dir) { - char dir[MX_DIRLEN]; - - MX_PROCFS_REMOVE_FILE(mx_ttid, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_boot_count, mxproc->procfs_ctrl_dir); - MX_PROCFS_REMOVE_FILE(mx_release, mxproc->procfs_info_dir); - MX_PROCFS_REMOVE_FILE(mx_rf_hw_ver, mxproc->procfs_info_dir); - MX_PROCFS_REMOVE_FILE(mx_rf_hw_name, mxproc->procfs_info_dir); - (void)snprintf(dir, sizeof(dir), "%s", procdir_info); - remove_proc_entry(dir, NULL); - mxproc->procfs_info_dir = NULL; - SCSC_TAG_DEBUG(MX_PROC, "removed %s proc dir\n", dir); - } -} diff --git a/drivers/misc/samsung/scsc/mxproc.h b/drivers/misc/samsung/scsc/mxproc.h deleted file mode 100644 index fcaae23cadcb..000000000000 --- a/drivers/misc/samsung/scsc/mxproc.h +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* - * mx140 proc interface - */ - -#ifndef MXPROC_H -#define MXPROC_H - -struct mxproc; - -int mxproc_create_ctrl_proc_dir(struct mxproc *mxproc, struct mxman *mxman); -void mxproc_remove_ctrl_proc_dir(struct mxproc *mxproc); -int mxproc_create_info_proc_dir(struct mxproc *mxproc, struct mxman *mxman); -void mxproc_remove_info_proc_dir(struct mxproc *mxproc); -extern int scsc_mx_list_services(struct mxman *mxman_p, char *buf, const size_t bufsz); -extern int mxman_print_rf_hw_version(struct mxman *mxman, char *buf, const size_t bufsz); - -struct mxproc { - struct mxman *mxman; - struct proc_dir_entry *procfs_ctrl_dir; - u32 procfs_ctrl_dir_num; - struct proc_dir_entry *procfs_info_dir; -}; - -#endif /* MXPROC_H */ diff --git a/drivers/misc/samsung/scsc/mxsyserr.c b/drivers/misc/samsung/scsc/mxsyserr.c deleted file mode 100755 index 8225f91408fe..000000000000 --- a/drivers/misc/samsung/scsc/mxsyserr.c +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scsc_mx_impl.h" -#include "miframman.h" -#include "mifmboxman.h" -#include "mxman.h" -#include "srvman.h" -#include "mxmgmt_transport.h" -#include "mxlog.h" -#include "mxlogger.h" -#include "fw_panic_record.h" -#include "panicmon.h" -#include "mxproc.h" -#include "mxsyserr.h" -#include "scsc/scsc_log_collector.h" - -#include -#include -#include - -/* If limits below are exceeded, a service level reset will be raised to level 7 */ -#define SYSERR_RESET_HISTORY_SIZE (4) -/* Minimum time between system error service resets (ms) */ -#define SYSERR_RESET_MIN_INTERVAL (300000) -/* No more then SYSERR_RESET_HISTORY_SIZE system error service resets in this period (ms)*/ -#define SYSERR_RESET_MONITOR_PERIOD (3600000) - - -/* Time stamps of last service resets in jiffies */ -static unsigned long syserr_reset_history[SYSERR_RESET_HISTORY_SIZE] = {0}; -static int syserr_reset_history_index; - -static uint syserr_reset_min_interval = SYSERR_RESET_MIN_INTERVAL; -module_param(syserr_reset_min_interval, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(syserr_reset_min_interval, "Minimum time between system error service resets (ms)"); - -static uint syserr_reset_monitor_period = SYSERR_RESET_MONITOR_PERIOD; -module_param(syserr_reset_monitor_period, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(syserr_reset_monitor_period, "No more then 4 system error service resets in this period (ms)"); - - -void mx_syserr_init(void) -{ - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_INIT: syserr_reset_min_interval %lu syserr_reset_monitor_period %lu\n", - syserr_reset_min_interval, syserr_reset_monitor_period); -} - -void mx_syserr_handler(struct mxman *mxman, const void *message) -{ - const struct mx_syserr_msg *msg = (const struct mx_syserr_msg *)message; - struct srvman *srvman; - - struct mx_syserr_decode decode; - - srvman = scsc_mx_get_srvman(mxman->mx); - - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND len: %u, ts: 0x%08X, tf: 0x%08X, str: 0x%x, code: 0x%08x, p0: 0x%x, p1: 0x%x\n", - msg->syserr.length, - msg->syserr.slow_clock, - msg->syserr.fast_clock, - msg->syserr.string_index, - msg->syserr.syserr_code, - msg->syserr.param[0], - msg->syserr.param[1]); - - decode.subsys = (u8) ((msg->syserr.syserr_code >> SYSERR_SUB_SYSTEM_POSN) & SYSERR_SUB_SYSTEM_MASK); - decode.level = (u8) ((msg->syserr.syserr_code >> SYSERR_LEVEL_POSN) & SYSERR_LEVEL_MASK); - decode.type = (u8) ((msg->syserr.syserr_code >> SYSERR_TYPE_POSN) & SYSERR_TYPE_MASK); - decode.subcode = (u16) ((msg->syserr.syserr_code >> SYSERR_SUB_CODE_POSN) & SYSERR_SUB_CODE_MASK); - - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND Subsys %d, Level %d, Type %d, Subcode 0x%04x\n", - decode.subsys, decode.level, decode.type, decode.subcode); - - /* Level 1 just gets logged without bothering anyone else */ - if (decode.level == MX_SYSERR_LEVEL_1) { - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x log only\n", - msg->syserr.syserr_code); - return; - } - - /* Ignore if panic reset in progress */ - if ((srvman->error) || (mxman->mxman_state == MXMAN_STATE_FAILED)) { - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x ignored (reset in progess)\n", - msg->syserr.syserr_code); - return; - } - - /* Ignore any system errors for the same sub-system if recovery is in progress */ - if ((mxman->syserr_recovery_in_progress) && (mxman->last_syserr.subsys == decode.subsys)) { - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x ignored (recovery in progess)\n", - msg->syserr.syserr_code); - return; - } - - - /* Let affected sevices escalate if needed - this also checks if only one sub-system is running - * and handles race conditions with shutting down service - */ - decode.level = srvman_notify_sub_system(srvman, &decode); - - if (decode.level >= MX_SYSERR_LEVEL_5) { - unsigned long now = jiffies; - int i; - - /* We use 0 as a NULL timestamp so avoid this */ - now = (now) ? now : 1; - - if ((decode.level == MX_SYSERR_LEVEL_7) || (mxman->syserr_recovery_in_progress)) { - /* If full reset has been requested or a service restart is needed and one is - * already in progress, trigger a full reset - */ - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x triggered full reset\n", - msg->syserr.syserr_code); - - mxman_fail(mxman, SCSC_PANIC_CODE_HOST << 15, __func__); - return; - } - - /* last_syserr_recovery_time is always zero-ed before we restart the chip */ - if (mxman->last_syserr_recovery_time) { - /* Have we had a too recent system error service reset - * Chance of false positive here is low enough to be acceptable - */ - if ((syserr_reset_min_interval) && (time_in_range(now, mxman->last_syserr_recovery_time, - mxman->last_syserr_recovery_time + msecs_to_jiffies(syserr_reset_min_interval)))) { - - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x triggered full reset (less than %dms after last)\n", - msg->syserr.syserr_code, syserr_reset_min_interval); - mxman_fail(mxman, SCSC_PANIC_CODE_HOST << 15, __func__); - return; - } else if (syserr_reset_monitor_period) { - /* Have we had too many system error service resets in one period? */ - /* This will be the case if all our stored history was in this period */ - bool out_of_danger_period_found = false; - - for (i = 0; (i < SYSERR_RESET_HISTORY_SIZE) && (!out_of_danger_period_found); i++) - out_of_danger_period_found = ((!syserr_reset_history[i]) || - (!time_in_range(now, syserr_reset_history[i], - syserr_reset_history[i] + msecs_to_jiffies(syserr_reset_monitor_period)))); - - if (!out_of_danger_period_found) { - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x triggered full reset (too many within %dms)\n", - msg->syserr.syserr_code, syserr_reset_monitor_period); - mxman_fail(mxman, SCSC_PANIC_CODE_HOST << 15, __func__); - return; - } - } - } else - /* First syserr service reset since chip was (re)started - zap history */ - for (i = 0; i < SYSERR_RESET_HISTORY_SIZE; i++) - syserr_reset_history[i] = 0; - - /* Otherwise trigger recovery of the affected subservices */ - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x triggered service recovery\n", - msg->syserr.syserr_code); - syserr_reset_history[syserr_reset_history_index++ % SYSERR_RESET_HISTORY_SIZE] = now; - mxman->last_syserr_recovery_time = now; - mxman_syserr(mxman, &decode); - } - -#ifdef CONFIG_SCSC_WLBTD -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Trigger sable log collection */ - SCSC_TAG_INFO(MXMAN, "MM_SYSERR_IND code: 0x%08x requested log collection\n", msg->syserr.syserr_code); - scsc_log_collector_schedule_collection(SCSC_LOG_SYS_ERR, decode.subcode); -#endif -#endif -} diff --git a/drivers/misc/samsung/scsc/mxsyserr.h b/drivers/misc/samsung/scsc/mxsyserr.h deleted file mode 100755 index 5991836897b4..000000000000 --- a/drivers/misc/samsung/scsc/mxsyserr.h +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __MX_SYSERR_H -#define __MX_SYSERR_H - - -struct mx_syserr { - u16 length; /* Length of this structure for future extension */ - u32 slow_clock; - u32 fast_clock; - u32 string_index; - u32 syserr_code; - u32 param[2]; -} __packed; - -struct mx_syserr_msg { - u8 id; - struct mx_syserr syserr; -} __packed; - -void mx_syserr_init(void); -void mx_syserr_handler(struct mxman *mx, const void *message); - -#endif diff --git a/drivers/misc/samsung/scsc/panic_record_r4_defs.h b/drivers/misc/samsung/scsc/panic_record_r4_defs.h deleted file mode 100644 index 4f631bac53fb..000000000000 --- a/drivers/misc/samsung/scsc/panic_record_r4_defs.h +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef PANIC_RECORD_R4_DEFS_H__ -#define PANIC_RECORD_R4_DEFS_H__ -/* - * R4 Panic Record Definitions. - * - * This record is used to pass summary information about the context of - * Maxwell R4 firmware panics to the host. - * - * The record location, relative to shared DRAM memory, is defined by the - * R4_PANIC_RECORD_OFFSET field in the firmware header [see SC-505846-SW]. - * - * Notes:- - * - The host panic handler should _not_ expect the R4 record to be - * written prior to a panic indication from Maxwell, and it may never - * be written at all. The checksum should indicate a valid record. - * - * N.B. Defined in this standalone header for inclusion in .s and .c. - */ - -/* - * The current version of the PANIC_RECORD_R4 structure defined below. - * Written to version field by firmware, checked by host. - * This also serves as a rudimentary endianess check. - */ -#define PANIC_RECORD_R4_VERSION_1 1 - -/* - * Total number of R4 registers saved. - */ -#define PANIC_RECORD_R4_REGISTER_COUNT 18 - -/* - * Number of panic info arguments. - */ -#define PANIC_RECORD_R4_INFO_COUNT 4 - -/* - * Checksum seed to prevent false match on all zeros or ones. - */ -#define PANIC_RECORD_R4_CKSUM_SEED 0xa5a5a5a5 - -/***************************************************************************** - * R4 Panic Record 32bit field indices. - *****************************************************************************/ - -/* - * Version of this structure. - */ -#define PANIC_RECORD_R4_VERSION_INDEX 0 - -/* - * Clock counters at time of the R4 panic. - * - * The 1M clock is generally the most useful but there is period - * after IP wake-up when it is not monotonic. The 32K count - * is included in-case of a panic during wake-up. - */ -#define PANIC_RECORD_R4_TIMESTAMP_1M_INDEX (PANIC_RECORD_R4_VERSION_INDEX + 1) -#define PANIC_RECORD_R4_TIMESTAMP_32K_INDEX (PANIC_RECORD_R4_TIMESTAMP_1M_INDEX + 1) - -/* - * Snapshot of main r4 CPU registers. - */ -#define PANIC_RECORD_R4_REGISTERS_INDEX (PANIC_RECORD_R4_TIMESTAMP_32K_INDEX + 1) - -/* - * Panic info. - * - * 1st field is key/index of panic_string. - */ -#define PANIC_RECORD_R4_INFO_INDEX (PANIC_RECORD_R4_REGISTERS_INDEX + PANIC_RECORD_R4_REGISTER_COUNT) - -/* - * 32bit XOR of all the fields above + PANIC_RECORD_R4_CKSUM_SEED - * - * Written by firmware on panic, checked by host. - */ -#define PANIC_RECORD_R4_CKSUM_INDEX (PANIC_RECORD_R4_INFO_INDEX + PANIC_RECORD_R4_INFO_COUNT) - -/* - * Length of the r4 panic record (uint32s). - */ -#define PANIC_RECORD_R4_LEN (PANIC_RECORD_R4_CKSUM_INDEX + 1) - -/***************************************************************************** - * R4 uint32 Register indices relative to PANIC_RECORD_R4_REGISTERS_INDEX - *****************************************************************************/ - -#define PANIC_RECORD_R4_REGISTER_R0 0 -#define PANIC_RECORD_R4_REGISTER_R1 1 -#define PANIC_RECORD_R4_REGISTER_R2 2 -#define PANIC_RECORD_R4_REGISTER_R3 3 -#define PANIC_RECORD_R4_REGISTER_R4 4 -#define PANIC_RECORD_R4_REGISTER_R5 5 -#define PANIC_RECORD_R4_REGISTER_R6 6 -#define PANIC_RECORD_R4_REGISTER_R7 7 -#define PANIC_RECORD_R4_REGISTER_R8 8 -#define PANIC_RECORD_R4_REGISTER_R9 9 -#define PANIC_RECORD_R4_REGISTER_R10 10 -#define PANIC_RECORD_R4_REGISTER_R11 11 -#define PANIC_RECORD_R4_REGISTER_R12 12 -#define PANIC_RECORD_R4_REGISTER_SP 13 -#define PANIC_RECORD_R4_REGISTER_LR 14 -#define PANIC_RECORD_R4_REGISTER_SPSR 15 -#define PANIC_RECORD_R4_REGISTER_PC 16 -#define PANIC_RECORD_R4_REGISTER_CPSR 17 - -/***************************************************************************** - * R4 Register octet offsets relative to PANIC_RECORD_R4_REGISTERS_INDEX - *****************************************************************************/ - -#define PANIC_RECORD_R4_REGISTER_OFFSET_R0 (PANIC_RECORD_R4_REGISTER_R0 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R1 (PANIC_RECORD_R4_REGISTER_R1 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R2 (PANIC_RECORD_R4_REGISTER_R2 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R3 (PANIC_RECORD_R4_REGISTER_R3 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R4 (PANIC_RECORD_R4_REGISTER_R4 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R5 (PANIC_RECORD_R4_REGISTER_R5 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R6 (PANIC_RECORD_R4_REGISTER_R6 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R7 (PANIC_RECORD_R4_REGISTER_R7 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R8 (PANIC_RECORD_R4_REGISTER_R8 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R9 (PANIC_RECORD_R4_REGISTER_R9 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R10 (PANIC_RECORD_R4_REGISTER_R10 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R11 (PANIC_RECORD_R4_REGISTER_R11 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_R12 (PANIC_RECORD_R4_REGISTER_R12 * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_SP (PANIC_RECORD_R4_REGISTER_SP * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_LR (PANIC_RECORD_R4_REGISTER_LR * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_SPSR (PANIC_RECORD_R4_REGISTER_SPSR * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_PC (PANIC_RECORD_R4_REGISTER_PC * 4) -#define PANIC_RECORD_R4_REGISTER_OFFSET_CPSR (PANIC_RECORD_R4_REGISTER_CPSR * 4) - -#endif /* PANIC_RECORD_R4_DEFS_H__ */ - diff --git a/drivers/misc/samsung/scsc/panicmon.c b/drivers/misc/samsung/scsc/panicmon.c deleted file mode 100644 index 90a960deca1c..000000000000 --- a/drivers/misc/samsung/scsc/panicmon.c +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#include - -#include "panicmon.h" -#include "scsc_mif_abs.h" -#include "mxman.h" - -static void panicmon_isr(int irq, void *data) -{ - struct panicmon *panicmon = (struct panicmon *)data; - - SCSC_TAG_DEBUG(PANIC_MON, "panicmon=%p panicmon->mx=%p mxman=%p\n", panicmon, panicmon->mx, scsc_mx_get_mxman(panicmon->mx)); - /* Avoid unused parameter error */ - (void)irq; - mxman_fail(scsc_mx_get_mxman(panicmon->mx), SCSC_PANIC_CODE_FW << 15, __func__); -} - - -void panicmon_init(struct panicmon *panicmon, struct scsc_mx *mx) -{ - struct scsc_mif_abs *mif; - - panicmon->mx = mx; - mif = scsc_mx_get_mif_abs(mx); - /* register isr with mif abstraction */ - mif->irq_reg_reset_request_handler(mif, panicmon_isr, (void *)panicmon); -} - -void panicmon_deinit(struct panicmon *panicmon) -{ - struct scsc_mif_abs *mif; - - mif = scsc_mx_get_mif_abs(panicmon->mx); - mif->irq_unreg_reset_request_handler(mif); -} diff --git a/drivers/misc/samsung/scsc/panicmon.h b/drivers/misc/samsung/scsc/panicmon.h deleted file mode 100644 index cbc9c7da964f..000000000000 --- a/drivers/misc/samsung/scsc/panicmon.h +++ /dev/null @@ -1,20 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#ifndef _PANICMON_H -#define _PANICMON_H -#include "mxman.h" - -struct panicmon; - -void panicmon_init(struct panicmon *panicmon, struct scsc_mx *mx); -void panicmon_deinit(struct panicmon *panicmon); - -struct panicmon { - struct scsc_mx *mx; -}; - -#endif /* _PANICMON_H */ diff --git a/drivers/misc/samsung/scsc/pcie_mbox.c b/drivers/misc/samsung/scsc/pcie_mbox.c deleted file mode 100644 index 3c9012f68e15..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mbox.c +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Mailbox Hardware Emulation (Implementation) -* -****************************************************************************/ - -/* Implements */ - -#include "pcie_mbox.h" - -/* Uses */ - -#include -#include -#include -#include "pcie_mbox_shared_data.h" -#include "pcie_mbox_intgen.h" - -/* Private Functions */ - -/** - * Initialise the mailbox emulation shared structure. - */ -static void pcie_mbox_shared_data_init(struct pcie_mbox_shared_data *shared_data) -{ - memset(shared_data, 0, sizeof(*shared_data)); - shared_data->magic = PCIE_MIF_MBOX_MAGIC_NUMBER; - shared_data->version = PCIE_MIF_MBOX_VERSION_NUMBER; - pcie_mbox_shared_data_wmb(); -} - -/* Public Functions */ - -void pcie_mbox_init( - struct pcie_mbox *mbox, - void *shared_data_region, - __iomem void *pcie_registers, - struct functor *ap_interrupt_trigger, - struct functor *r4_interrupt_trigger, -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - struct functor *m4_interrupt_trigger, - struct functor *m4_1_interrupt_trigger -#else - struct functor *m4_interrupt_trigger -#endif - ) -{ - mbox->shared_data = (struct pcie_mbox_shared_data *)shared_data_region; - - pcie_mbox_shared_data_init(mbox->shared_data); - - /* Interrupt Generator Emulations */ - - pcie_mbox_intgen_init(&mbox->ap_intgen, "AP", &mbox->shared_data->ap_interrupt, ap_interrupt_trigger); - pcie_mbox_intgen_init(&mbox->r4_intgen, "R4", &mbox->shared_data->r4_interrupt, r4_interrupt_trigger); - pcie_mbox_intgen_init(&mbox->m4_intgen, "M4", &mbox->shared_data->m4_interrupt, m4_interrupt_trigger); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - pcie_mbox_intgen_init(&mbox->m4_intgen_1, "M4", &mbox->shared_data->m4_1_interrupt, m4_1_interrupt_trigger); -#endif -} - -u32 pcie_mbox_get_ap_interrupt_masked_bitmask(const struct pcie_mbox *mbox) -{ - /* Delegate to ap intgen component */ - return pcie_mbox_intgen_get_masked_bitmask(&mbox->ap_intgen); -} - -u32 pcie_mbox_get_ap_interrupt_pending_bitmask(const struct pcie_mbox *mbox) -{ - /* Delegate to ap intgen component */ - return pcie_mbox_intgen_get_pending_bitmask(&mbox->ap_intgen); -} - -bool pcie_mbox_is_ap_interrupt_source_pending(const struct pcie_mbox *mbox, int source_num) -{ - return pcie_mbox_intgen_is_source_pending(&mbox->ap_intgen, source_num); -} - -void pcie_mbox_clear_ap_interrupt_source(struct pcie_mbox *mbox, int source_num) -{ - /* Delegate to ap intgen component */ - pcie_mbox_intgen_clear_source(&mbox->ap_intgen, source_num); -} - -void pcie_mbox_mask_ap_interrupt_source(struct pcie_mbox *mbox, int source_num) -{ - /* Delegate to ap intgen component */ - pcie_mbox_intgen_mask_source(&mbox->ap_intgen, source_num); -} - -void pcie_mbox_unmask_ap_interrupt_source(struct pcie_mbox *mbox, int source_num) -{ - /* Delegate to ap intgen component */ - pcie_mbox_intgen_unmask_source(&mbox->ap_intgen, source_num); -} - -void pcie_mbox_set_outgoing_interrupt_source(struct pcie_mbox *mbox, enum scsc_mif_abs_target target_node, int source_num) -{ - /* Delegate to appropriate intgen instance*/ - switch (target_node) { - case SCSC_MIF_ABS_TARGET_R4: - pcie_mbox_intgen_set_source(&mbox->r4_intgen, source_num); - break; - case SCSC_MIF_ABS_TARGET_M4: - pcie_mbox_intgen_set_source(&mbox->m4_intgen, source_num); - break; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - case SCSC_MIF_ABS_TARGET_M4_1: - pcie_mbox_intgen_set_source(&mbox->m4_intgen, source_num); - break; -#endif - default: - SCSC_TAG_ERR(PCIE_MIF, "Invalid interrupt target %d\n", target_node); - return; - } -} - -u32 *pcie_mbox_get_mailbox_ptr(struct pcie_mbox *mbox, u32 mbox_index) -{ - if (mbox_index >= PCIE_MIF_MBOX_ISSR_COUNT) { - SCSC_TAG_ERR(PCIE_MIF, "Invalid mailbox index %d\n", mbox_index); - return NULL; - } - - return &mbox->shared_data->mailbox[mbox_index]; -} - diff --git a/drivers/misc/samsung/scsc/pcie_mbox.h b/drivers/misc/samsung/scsc/pcie_mbox.h deleted file mode 100644 index 04bb9dfdb0a5..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mbox.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Mailbox Hardware Emulation (Interface) -* -****************************************************************************/ - -#ifndef __PCIE_MBOX_H -#define __PCIE_MBOX_H - -/* Uses */ - -#include "scsc_mif_abs.h" /* for enum scsc_mif_abs_target */ -#include "pcie_mbox_intgen.h" - -/* Forward */ - -struct pcie_mbox_shared_data; - -/* Types */ - -/** - * Maxwell Mailbox Hardware Emulation. - * - * Uses structure in shared memory to emulate the MX Mailbox Hardware in - * conjunction with matching logic in R4 & M4 firmware. - * - * The emulated hardware includes an array of simple 32 bit mailboxes and - * 3 instances of Interrupt Generator (intgen) hardware (to ap, to r4 & to m4). - */ -struct pcie_mbox { - /** Pointer to shared Mailbox emulation state */ - struct pcie_mbox_shared_data *shared_data; - - /** Interrupt Generator Emulations */ - struct pcie_mbox_intgen ap_intgen; - struct pcie_mbox_intgen r4_intgen; - struct pcie_mbox_intgen m4_intgen; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - struct pcie_mbox_intgen m4_intgen_1; -#endif -}; - -/* Public Functions */ - -/** - * Initialise the mailbox emulation. - */ -void pcie_mbox_init( - struct pcie_mbox *mbox, - void *shared_data_region, - __iomem void *pcie_registers, - struct functor *ap_interrupt_trigger, - struct functor *r4_interrupt_trigger, -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - struct functor *m4_interrupt_trigger, - struct functor *m4_1_interrupt_trigger -#else - struct functor *m4_interrupt_trigger -#endif - ); - -/** - * Get the AP interrupt source mask state as a bitmask. - */ -u32 pcie_mbox_get_ap_interrupt_masked_bitmask(const struct pcie_mbox *mbox); - -/** - * Get the AP interrupt source pending (set and not masked) state as a bitmask. - */ -u32 pcie_mbox_get_ap_interrupt_pending_bitmask(const struct pcie_mbox *mbox); - -/** - * Is the specified AP interrupt source pending (set and not masked)? - */ -bool pcie_mbox_is_ap_interrupt_source_pending(const struct pcie_mbox *mbox, int source_num); - -/** - * Clear the specified AP interrupt source. - */ -void pcie_mbox_clear_ap_interrupt_source(struct pcie_mbox *mbox, int source_num); - -/** - * Mask the specified AP interrupt source. - */ -void pcie_mbox_mask_ap_interrupt_source(struct pcie_mbox *mbox, int source_num); - -/** - * Unmask the specified AP interrupt source. - * - * The interrupt will trigger if the source is currently set. - */ -void pcie_mbox_unmask_ap_interrupt_source(struct pcie_mbox *mbox, int source_num); - -/** - * Set an outgoing interrupt source to R4 or M4 node. - * - * Triggers interrupt in target node if the source is not masked. - */ -void pcie_mbox_set_outgoing_interrupt_source(struct pcie_mbox *mbox, enum scsc_mif_abs_target target_node, int source_num); - -/** - * Get pointer to the specified 32bit Mailbox in shared memory. - */ -u32 *pcie_mbox_get_mailbox_ptr(struct pcie_mbox *mbox, u32 mbox_index); - -#endif /* __PCIE_MBOX_H */ - diff --git a/drivers/misc/samsung/scsc/pcie_mbox_intgen.c b/drivers/misc/samsung/scsc/pcie_mbox_intgen.c deleted file mode 100644 index a9d6ff839b9f..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mbox_intgen.c +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Mailbox Interrupt Generator Emulation (Implementation) -* -****************************************************************************/ - -/* Implements */ - -#include "pcie_mbox_intgen.h" - -/* Uses */ - -#include "pcie_mbox_intgen_shared_data.h" -#include "functor.h" -#include - -/* Private Functions */ - -/** - * Trigger the hardware interrupt associated with this Interrupt Generator. - */ -static void pcie_mbox_intgen_trigger_interrupt(struct pcie_mbox_intgen *intgen) -{ - /* Implementation is abstracted to hide the differences from this module */ - functor_call(intgen->trigger_interrupt_fn); -} - -/* Public Functions */ - -void pcie_mbox_intgen_init( - struct pcie_mbox_intgen *intgen, - const char *name, - struct pcie_mbox_intgen_shared_data *shared_data, - struct functor *trigger_interrupt_fn - ) -{ - strncpy(intgen->name, name, sizeof(intgen->name)); - intgen->shared_data = shared_data; - intgen->trigger_interrupt_fn = trigger_interrupt_fn; -} - -u32 pcie_mbox_intgen_get_masked_bitmask(const struct pcie_mbox_intgen *intgen) -{ - /* Compile bitmask from the emulation's separate source mask fields */ - - u32 masked_bitmask = 0; - int source_num; - - for (source_num = 0; source_num < PCIE_MIF_MBOX_NUM_INTR_SOURCES; ++source_num) - if (intgen->shared_data->mask[source_num]) - masked_bitmask |= (1 << source_num); - - return masked_bitmask; -} - -bool pcie_mbox_intgen_is_source_pending(const struct pcie_mbox_intgen *intgen, int source_num) -{ - return intgen->shared_data->status[source_num] && !intgen->shared_data->mask[source_num]; -} - -u32 pcie_mbox_intgen_get_pending_bitmask(const struct pcie_mbox_intgen *intgen) -{ - /* Compile bitmask from the emulation's separate source status and mask fields */ - - u32 pending_bitmask = 0; - int source_num; - - for (source_num = 0; source_num < PCIE_MIF_MBOX_NUM_INTR_SOURCES; ++source_num) - if (pcie_mbox_intgen_is_source_pending(intgen, source_num)) - pending_bitmask |= (1 << source_num); - - return pending_bitmask; -} - -void pcie_mbox_intgen_set_source(struct pcie_mbox_intgen *intgen, int source_num) -{ - if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) { - SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num); - return; - } - - SCSC_TAG_DEBUG(PCIE_MIF, "Set source %s:%d. (P %08x, M %08x)\n", - intgen->name, source_num, - pcie_mbox_intgen_get_pending_bitmask(intgen), - pcie_mbox_intgen_get_masked_bitmask(intgen) - ); - - intgen->shared_data->status[source_num] = 1; - pcie_mbox_shared_data_wmb(); - if (!intgen->shared_data->mask[source_num]) - pcie_mbox_intgen_trigger_interrupt(intgen); -} - -void pcie_mbox_intgen_clear_source(struct pcie_mbox_intgen *intgen, int source_num) -{ - if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) { - SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num); - return; - } - - SCSC_TAG_DEBUG(PCIE_MIF, "Clear source %s:%d. (P %08x, M %08x)\n", - intgen->name, source_num, - pcie_mbox_intgen_get_pending_bitmask(intgen), - pcie_mbox_intgen_get_masked_bitmask(intgen) - ); - - intgen->shared_data->status[source_num] = 0; - pcie_mbox_shared_data_wmb(); -} - -void pcie_mbox_intgen_mask_source(struct pcie_mbox_intgen *intgen, int source_num) -{ - if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) { - SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num); - return; - } - - SCSC_TAG_DEBUG(PCIE_MIF, "Mask source %s:%d.\n", intgen->name, source_num); - - intgen->shared_data->mask[source_num] = 1; - pcie_mbox_shared_data_wmb(); -} - -void pcie_mbox_intgen_unmask_source(struct pcie_mbox_intgen *intgen, int source_num) -{ - if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) { - SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num); - return; - } - - SCSC_TAG_DEBUG(PCIE_MIF, "UnMask source %s:%d.\n", intgen->name, source_num); - - intgen->shared_data->mask[source_num] = 0; - pcie_mbox_shared_data_wmb(); - if (intgen->shared_data->status[source_num]) - pcie_mbox_intgen_trigger_interrupt(intgen); -} - diff --git a/drivers/misc/samsung/scsc/pcie_mbox_intgen.h b/drivers/misc/samsung/scsc/pcie_mbox_intgen.h deleted file mode 100644 index b76c198e4757..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mbox_intgen.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Mailbox Interrupt Generator Emulation (Interface) -* -****************************************************************************/ - -#ifndef __PCIE_MBOX_INTGEN_H -#define __PCIE_MBOX_INTGEN_H - -/* Uses */ - -#include "linux/types.h" - -/* Forward Types */ - -struct pcie_mbox_intgen_shared_data; -struct functor; - -/* Public Types */ - -/** - * Maxwell Mailbox Interrupt Generator Emulation descriptor - * - * Uses structures in shared memory to emulate the Interrupt Generation - * Hardware in conjunction with matching logic in R4 & M4 firmware. - * - * This is used to implement 3 instances of the Interrupt Generation (intgen) - * hardware (to ap, to r4 & to m4). - */ -struct pcie_mbox_intgen { - char name[16]; - struct pcie_mbox_intgen_shared_data *shared_data; - struct functor *trigger_interrupt_fn; -}; - -/* Public Functions */ - -/** - * Initialise this Interrupt Generator. - */ -void pcie_mbox_intgen_init( - - /** This Interrupt Generator emulation */ - struct pcie_mbox_intgen *intgen, - - /** Name for debugging purposes */ - const char *name, - - /** Pointer to shared data for this emulation */ - struct pcie_mbox_intgen_shared_data *shared_data, - - /** - * Functor to trigger associated hardware interrupt. - * - * The trigger is abstracted so that the same logic can be - * re-used for the incoming and outgoing emulations. - */ - struct functor *trigger_interrupt_fn - ); - -/** - * Get this Interrupt Generator's source masked state as a bitmask. - */ -u32 pcie_mbox_intgen_get_masked_bitmask(const struct pcie_mbox_intgen *intgen); - -/** - * Get this Interrupt Generator's source pending state (set and not masked) as a bitmask. - */ -u32 pcie_mbox_intgen_get_pending_bitmask(const struct pcie_mbox_intgen *intgen); - -/** - * Set specified Interrupt Generator source. - * - * Triggers interrupt on the interrupt target if the source is not masked. - */ -void pcie_mbox_intgen_set_source(struct pcie_mbox_intgen *intgen, int source_num); - -/** - * Clear specified Interrupt Generator source. - */ -void pcie_mbox_intgen_clear_source(struct pcie_mbox_intgen *intgen, int source_num); - -/** - * Mask specified Interrupt Generator source. - */ -void pcie_mbox_intgen_mask_source(struct pcie_mbox_intgen *intgen, int source_num); - -/** - * Unmask specified Interrupt Generator source. - * - * The associated hardware interrupt will be triggered if - * the specified source is currently set. - */ -void pcie_mbox_intgen_unmask_source(struct pcie_mbox_intgen *intgen, int source_num); - -/** - * Is the specified interrupt source pending (set and not masked)? - */ -bool pcie_mbox_intgen_is_source_pending(const struct pcie_mbox_intgen *intgen, int source_num); - - -#endif /* __PCIE_MBOX_INTGEN_H */ - diff --git a/drivers/misc/samsung/scsc/pcie_mbox_intgen_shared_data.h b/drivers/misc/samsung/scsc/pcie_mbox_intgen_shared_data.h deleted file mode 100644 index ff0dd5cb8b6f..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mbox_intgen_shared_data.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Software Mailbox Interrupt Generator Emulation shared data -* structure. -* -****************************************************************************/ - -#ifndef __PCIE_MBOX_INTGEN_SHARED_DATA_H -#define __PCIE_MBOX_INTGEN_SHARED_DATA_H - -/* Uses */ - -#include "pcie_mbox_shared_data_defs.h" -#include "linux/types.h" - -/* Types */ - -/** - * Mailbox Interrupt Generator Emulation shared state. - * - * Notes: - * - Structure must be packed. - * - All integers are LittleEndian. - */ -PCI_MBOX_SHARED_DATA_ATTR struct pcie_mbox_intgen_shared_data { - /** Interrupt source mask state (whole word each to avoid RMW issues) */ - uint32_t mask[PCIE_MIF_MBOX_NUM_INTR_SOURCES]; - /** Interrupt source set state (whole word each to avoid RMW issues) */ - uint32_t status[PCIE_MIF_MBOX_NUM_INTR_SOURCES]; -}; - -#endif /* __PCIE_MBOX_INTGEN_SHARED_DATA_H */ - diff --git a/drivers/misc/samsung/scsc/pcie_mbox_shared_data.h b/drivers/misc/samsung/scsc/pcie_mbox_shared_data.h deleted file mode 100644 index 40dcb0f8f12e..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mbox_shared_data.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Software Mailbox Emulation shared data structure. -* -* Ref: SC-506707-DD - Structure version 2 -* -****************************************************************************/ - -#ifndef __PCIE_MBOX_SHARED_DATA_H -#define __PCIE_MBOX_SHARED_DATA_H - -/* Uses */ - -#include "pcie_mbox_shared_data_defs.h" -#include "pcie_mbox_intgen_shared_data.h" - -/* Types */ - -/** - * Mailbox Emulation Generator shared state. - * - * Notes: - * - Structure must be packed. - * - All integers are LittleEndian. - */ -PCI_MBOX_SHARED_DATA_ATTR struct pcie_mbox_shared_data { - uint32_t mailbox[PCIE_MIF_MBOX_ISSR_COUNT]; - uint32_t magic; - uint32_t version; - struct pcie_mbox_intgen_shared_data ap_interrupt; - struct pcie_mbox_intgen_shared_data r4_interrupt; - struct pcie_mbox_intgen_shared_data m4_interrupt; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - struct pcie_mbox_intgen_shared_data m4_1_interrupt; -#endif -}; - -#endif /* __PCIE_MBOX_SHARED_DATA_H */ - diff --git a/drivers/misc/samsung/scsc/pcie_mbox_shared_data_defs.h b/drivers/misc/samsung/scsc/pcie_mbox_shared_data_defs.h deleted file mode 100644 index fe9227ed234a..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mbox_shared_data_defs.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -* Maxwell Software Mailbox Emulation shared data definitions. -* -* Ref: SC-506707-DD - Structure version 2 -* -****************************************************************************/ - -#ifndef __PCIE_MBOX_SHARED_DATA_DEFS_H -#define __PCIE_MBOX_SHARED_DATA_DEFS_H - -/* Defines */ - -/** Offset of shared data structure from end of shared ram */ -#define PCIE_MIF_MBOX_RESERVED_LEN (0x400) - -#define PCIE_MIF_MBOX_MAGIC_NUMBER (0x3a11b0c5) - -#define PCIE_MIF_MBOX_VERSION_NUMBER (0x00000002) - -/** - * Number of mailboxes. - * - * Note: Current hardware supports 16 mailboxes. The extra mailboxes - * in the emulation may be used to emulate other signals. - */ -#define PCIE_MIF_MBOX_ISSR_COUNT (32) - -/** - * Number of interrupt sources per Interrupt Generator Emulation instance. - * - * Note: Current hardware supports 16 sources. The extra sources - * in the emulation may be used to emulate other signals - * (e.g. RESET_REQUEST from MX to AP). - * - */ -#define PCIE_MIF_MBOX_NUM_INTR_SOURCES (32) - -/** - * Structure must be packed. - */ -#define PCI_MBOX_SHARED_DATA_ATTR __packed - -/** - * Write barrier for syncing writes to pcie_mbox_shared_data - * shared data area. - * - * HERE: Can we use something lighter? E.g. dma_wmb()? - */ -#define pcie_mbox_shared_data_wmb() wmb() - -#endif /* __PCIE_MBOX_SHARED_DATA_DEFS_H */ - diff --git a/drivers/misc/samsung/scsc/pcie_mif.c b/drivers/misc/samsung/scsc/pcie_mif.c deleted file mode 100644 index c889ff9dd798..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mif.c +++ /dev/null @@ -1,701 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved -* -****************************************************************************/ - -/* Implements */ - -#include "pcie_mif.h" - -/* Uses */ - -#include -#include -#include -#include -#include -#include -#include "pcie_mif_module.h" -#include "pcie_proc.h" -#include "pcie_mbox.h" -#include "functor.h" - -#define PCIE_MIF_RESET_REQUEST_SOURCE 31 - -/* Module parameters */ - -static bool enable_pcie_mif_arm_reset = true; -module_param(enable_pcie_mif_arm_reset, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_pcie_mif_arm_reset, "Enables ARM cores reset"); - -/* Types */ - -struct pcie_mif { - struct scsc_mif_abs interface; - struct pci_dev *pdev; - int dma_using_dac; /* =1 if 64-bit DMA is used, =0 otherwise. */ - __iomem void *registers; - - struct device *dev; - - u8 *mem; /* DMA memory mapped to PCIe space for MX-AP comms */ - struct pcie_mbox mbox; /* mailbox emulation */ - size_t mem_allocated; - dma_addr_t dma_addr; - - /* Callback function and dev pointer mif_intr manager handler */ - void (*r4_handler)(int irq, void *data); - void *irq_dev; - - /* Reset Request handler and context */ - void (*reset_request_handler)(int irq_num_ignored, void *data); - void *reset_request_handler_data; - - /** - * Functors to trigger, or simulate, MIF WLBT Mailbox interrupts. - * - * These functors isolates the Interrupt Generator logic - * from differences in physical interrupt generation. - */ - struct functor trigger_ap_interrupt; - struct functor trigger_r4_interrupt; - struct functor trigger_m4_interrupt; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - struct functor trigger_m4_1_interrupt; -#endif -}; - -/* Private Macros */ - -/** Upcast from interface member to pcie_mif */ -#define pcie_mif_from_mif_abs(MIF_ABS_PTR) container_of(MIF_ABS_PTR, struct pcie_mif, interface) - -/** Upcast from trigger_ap_interrupt member to pcie_mif */ -#define pcie_mif_from_trigger_ap_interrupt(trigger) container_of(trigger, struct pcie_mif, trigger_ap_interrupt) - -/** Upcast from trigger_r4_interrupt member to pcie_mif */ -#define pcie_mif_from_trigger_r4_interrupt(trigger) container_of(trigger, struct pcie_mif, trigger_r4_interrupt) - -/** Upcast from trigger_m4_interrupt member to pcie_mif */ -#define pcie_mif_from_trigger_m4_interrupt(trigger) container_of(trigger, struct pcie_mif, trigger_m4_interrupt) - -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT -/** Upcast from trigger_m4_interrupt member to pcie_mif */ -#define pcie_mif_from_trigger_m4_1_interrupt(trigger) container_of(trigger, struct pcie_mif, trigger_m4_1_interrupt) -#endif - -/* Private Functions */ - -static void pcie_mif_irq_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; -} - -static void pcie_mif_emulate_reset_request_interrupt(struct pcie_mif *pcie) -{ - /* The RESET_REQUEST interrupt is emulated over PCIe using a spare MIF interrupt source */ - if (pcie_mbox_is_ap_interrupt_source_pending(&pcie->mbox, PCIE_MIF_RESET_REQUEST_SOURCE)) { - /* Invoke handler if registered */ - if (pcie->reset_request_handler) - pcie->reset_request_handler(0, pcie->reset_request_handler_data); - /* Clear the source to emulate hardware interrupt behaviour */ - pcie_mbox_clear_ap_interrupt_source(&pcie->mbox, PCIE_MIF_RESET_REQUEST_SOURCE); - } -} - -#ifdef CONFIG_SCSC_QOS -static int pcie_mif_pm_qos_add_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - return 0; -} - -static int pcie_mif_pm_qos_update_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - return 0; -} - -static int pcie_mif_pm_qos_remove_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req) -{ - return 0; -} -#endif - -irqreturn_t pcie_mif_isr(int irq, void *data) -{ - struct pcie_mif *pcie = (struct pcie_mif *)data; - - SCSC_TAG_DEBUG(PCIE_MIF, "MIF Interrupt Received. (Pending 0x%08x, Mask 0x%08x)\n", - pcie_mbox_get_ap_interrupt_pending_bitmask(&pcie->mbox), - pcie_mbox_get_ap_interrupt_masked_bitmask(&pcie->mbox) - ); - - /* - * Intercept mailbox interrupt sources (numbers > 15) used to emulate other - * signalling paths missing from emulator/PCIe hardware. - */ - pcie_mif_emulate_reset_request_interrupt(pcie); - - /* Invoke the normal MIF interrupt handler */ - if (pcie->r4_handler != pcie_mif_irq_default_handler) - pcie->r4_handler(irq, pcie->irq_dev); - else - SCSC_TAG_INFO(PCIE_MIF, "Any handler registered\n"); - - return IRQ_HANDLED; -} - -/** - * Trigger, or simulate, inbound (to AP) PCIe interrupt. - * - * Called back via functor. - */ -static void pcie_mif_trigger_ap_interrupt(struct functor *trigger) -{ - struct pcie_mif *pcie = pcie_mif_from_trigger_ap_interrupt(trigger); - - /* - * Invoke the normal isr handler synchronously. - * - * If synchronous handling proves problematic then launch - * an async task or trigger GIC interrupt manually (if supported). - */ - (void)pcie_mif_isr(0, (void *)pcie); -}; - -/** - * Trigger PCIe interrupt to R4. - * - * Called back via functor. - */ -static void pcie_mif_trigger_r4_interrupt(struct functor *trigger) -{ - struct pcie_mif *pcie = pcie_mif_from_trigger_r4_interrupt(trigger); - - SCSC_TAG_DEBUG(PCIE_MIF, "Triggering R4 Mailbox interrupt.\n"); - - iowrite32(0x00000001, pcie->registers + SCSC_PCIE_NEWMSG); - mmiowb(); -}; - -/** - * Trigger PCIe interrupt to M4. - * - * Called back via functor. - */ -static void pcie_mif_trigger_m4_interrupt(struct functor *trigger) -{ - struct pcie_mif *pcie = pcie_mif_from_trigger_m4_interrupt(trigger); - - SCSC_TAG_DEBUG(PCIE_MIF, "Triggering M4 Mailbox interrupt.\n"); - - iowrite32(0x00000001, pcie->registers + SCSC_PCIE_NEWMSG2); - mmiowb(); -}; - -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT -/** - * Trigger PCIe interrupt to M4. - * - * Called back via functor. - */ -static void pcie_mif_trigger_m4_1_interrupt(struct functor *trigger) -{ - struct pcie_mif *pcie = pcie_mif_from_trigger_m4_1_interrupt(trigger); - - SCSC_TAG_DEBUG(PCIE_MIF, "Triggering M4 1 Mailbox interrupt.\n"); - - iowrite32(0x00000001, pcie->registers + SCSC_PCIE_NEWMSG3); - mmiowb(); -}; -#endif - -static void pcie_mif_destroy(struct scsc_mif_abs *interface) -{ - /* Avoid unused parameter error */ - (void)interface; -} - -static char *pcie_mif_get_uid(struct scsc_mif_abs *interface) -{ - /* Avoid unused parameter error */ - (void)interface; - /* TODO */ - /* return "0" for the time being */ - return "0"; -} - -static int pcie_mif_reset(struct scsc_mif_abs *interface, bool reset) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - int ret; - - if (enable_pcie_mif_arm_reset || !reset) { - /* Sanity check */ - iowrite32(0xdeadbeef, pcie->registers + SCSC_PCIE_SIGNATURE); - mmiowb(); - ret = ioread32(pcie->registers + SCSC_PCIE_SIGNATURE); - if (ret != 0xdeadbeef) { - SCSC_TAG_ERR_DEV(PCIE_MIF, pcie->dev, "Can't acces BAR0 magic number. Readed: 0x%x Expected: 0x%x\n", - ret, 0xdeadbeef); - return -ENODEV; - } - - iowrite32(reset ? 1 : 0, - pcie->registers + SCSC_PCIE_GRST_OFFSET); - mmiowb(); - } else - SCSC_TAG_INFO(PCIE_MIF, "Not resetting ARM Cores enable_pcie_mif_arm_reset: %d\n", - enable_pcie_mif_arm_reset); - return 0; -} - -static void *pcie_mif_map(struct scsc_mif_abs *interface, size_t *allocated) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - int ret; - size_t map_len = PCIE_MIF_ALLOC_MEM; - - if (allocated) - *allocated = 0; - - if (map_len > (PCIE_MIF_PREALLOC_MEM - 1)) { - SCSC_TAG_ERR(PCIE_MIF, "Error allocating DMA memory, requested %zu, maximum %d, consider different size\n", map_len, PCIE_MIF_PREALLOC_MEM); - return NULL; - } - - /* should return PAGE_ALIGN Memory */ - pcie->mem = dma_alloc_coherent(pcie->dev, - PCIE_MIF_PREALLOC_MEM, &pcie->dma_addr, GFP_KERNEL); - if (pcie->mem == NULL) { - SCSC_TAG_ERR(PCIE_MIF, "Error allocating %d DMA memory\n", PCIE_MIF_PREALLOC_MEM); - return NULL; - } - - pcie->mem_allocated = map_len; - - SCSC_TAG_INFO_DEV(PCIE_MIF, pcie->dev, "Allocated dma coherent mem: %p addr %p\n", pcie->mem, (void *)pcie->dma_addr); - - iowrite32((unsigned int)pcie->dma_addr, - pcie->registers + SCSC_PCIE_OFFSET); - mmiowb(); - ret = ioread32(pcie->registers + SCSC_PCIE_OFFSET); - SCSC_TAG_INFO(PCIE_MIF, "Read SHARED_BA 0x%0x\n", ret); - if (ret != (unsigned int)pcie->dma_addr) { - SCSC_TAG_ERR_DEV(PCIE_MIF, pcie->dev, "Can't acces BAR0 Shared BA. Readed: 0x%x Expected: 0x%x\n", ret, (unsigned int)pcie->dma_addr); - return NULL; - } - - /* Initialised the interrupt trigger functors required by mbox emulation */ - functor_init(&pcie->trigger_ap_interrupt, pcie_mif_trigger_ap_interrupt); - functor_init(&pcie->trigger_r4_interrupt, pcie_mif_trigger_r4_interrupt); - functor_init(&pcie->trigger_m4_interrupt, pcie_mif_trigger_m4_interrupt); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - functor_init(&pcie->trigger_m4_1_interrupt, pcie_mif_trigger_m4_1_interrupt); -#endif - - /* Initialise mailbox emulation to use shared memory at the end of PCIE_MIF_PREALLOC_MEM */ - pcie_mbox_init( - &pcie->mbox, - pcie->mem + PCIE_MIF_PREALLOC_MEM - PCIE_MIF_MBOX_RESERVED_LEN, - pcie->registers, - &pcie->trigger_ap_interrupt, - &pcie->trigger_r4_interrupt, -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - &pcie->trigger_m4_interrupt, - &pcie->trigger_m4_1_interrupt -#else - &pcie->trigger_m4_interrupt -#endif - ); - - /* Return the max allocatable memory on this abs. implementation */ - if (allocated) - *allocated = map_len; - - return pcie->mem; -} - -/* HERE: Not sure why mem is passed in - its stored in pcie - as it should be */ -static void pcie_mif_unmap(struct scsc_mif_abs *interface, void *mem) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* Avoid unused parameter error */ - (void)mem; - - dma_free_coherent(pcie->dev, PCIE_MIF_PREALLOC_MEM, pcie->mem, pcie->dma_addr); - SCSC_TAG_INFO_DEV(PCIE_MIF, pcie->dev, "Freed dma coherent mem: %p addr %p\n", pcie->mem, (void *)pcie->dma_addr); -} - -static u32 pcie_mif_irq_bit_mask_status_get(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* delegate to mbox emulation component */ - return pcie_mbox_get_ap_interrupt_masked_bitmask(&pcie->mbox); -} - -static u32 pcie_mif_irq_get(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* delegate to mbox emulation component */ - return pcie_mbox_get_ap_interrupt_pending_bitmask(&pcie->mbox); -} - -static void pcie_mif_irq_bit_clear(struct scsc_mif_abs *interface, int bit_num) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* delegate to mbox emulation component */ - pcie_mbox_clear_ap_interrupt_source(&pcie->mbox, bit_num); -} - -static void pcie_mif_irq_bit_mask(struct scsc_mif_abs *interface, int bit_num) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* delegate to mbox interrupt emulation component */ - pcie_mbox_mask_ap_interrupt_source(&pcie->mbox, bit_num); -} - -static void pcie_mif_irq_bit_unmask(struct scsc_mif_abs *interface, int bit_num) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* delegate to mbox emulation component */ - pcie_mbox_unmask_ap_interrupt_source(&pcie->mbox, bit_num); -} - -static void pcie_mif_irq_bit_set(struct scsc_mif_abs *interface, int bit_num, enum scsc_mif_abs_target target) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* delegate to mbox emulation sub-module */ - pcie_mbox_set_outgoing_interrupt_source(&pcie->mbox, target, bit_num); -} - -static void pcie_mif_irq_reg_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - pcie->r4_handler = handler; - pcie->irq_dev = dev; -} - -static void pcie_mif_irq_unreg_handler(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - pcie->r4_handler = pcie_mif_irq_default_handler; - pcie->irq_dev = NULL; -} - -static void pcie_mif_irq_reg_reset_request_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - pcie->reset_request_handler = handler; - pcie->reset_request_handler_data = dev; - - pcie_mbox_clear_ap_interrupt_source(&pcie->mbox, PCIE_MIF_RESET_REQUEST_SOURCE); - pcie_mbox_unmask_ap_interrupt_source(&pcie->mbox, PCIE_MIF_RESET_REQUEST_SOURCE); -} - -static void pcie_mif_irq_unreg_reset_request_handler(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - pcie_mbox_mask_ap_interrupt_source(&pcie->mbox, PCIE_MIF_RESET_REQUEST_SOURCE); - pcie->reset_request_handler = NULL; -} - -static u32 *pcie_mif_get_mbox_ptr(struct scsc_mif_abs *interface, u32 mbox_index) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - /* delegate to mbox emulation sub-module */ - return pcie_mbox_get_mailbox_ptr(&pcie->mbox, mbox_index); -} - -static int pcie_mif_get_mifram_ref(struct scsc_mif_abs *interface, void *ptr, scsc_mifram_ref *ref) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - if ((u8 *)ptr > (pcie->mem + 4 * 1024 * 1024)) { - SCSC_TAG_ERR(PCIE_MIF, "ooops limits reached\n"); - return -ENOMEM; - } - - /* Ref is byte offset wrt start of shared memory */ - *ref = (scsc_mifram_ref)((uintptr_t)ptr - (uintptr_t)pcie->mem); - - return 0; -} - -static void *pcie_mif_get_mifram_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PCIE_MIF, pcie->dev, "\n"); - - /* Check limits */ - if (ref >= 0 && ref < PCIE_MIF_ALLOC_MEM) - return (void *)((uintptr_t)pcie->mem + (uintptr_t)ref); - else - return NULL; -} - -static uintptr_t pcie_mif_get_mif_pfn(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - return virt_to_phys(pcie->mem) >> PAGE_SHIFT; -} - -static struct device *pcie_mif_get_mif_device(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - return pcie->dev; -} - -static void pcie_mif_irq_clear(void) -{ -} - -static void pcie_mif_dump_register(struct scsc_mif_abs *interface) -{ -} - -struct scsc_mif_abs *pcie_mif_create(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int rc = 0; - struct scsc_mif_abs *pcie_if; - struct pcie_mif *pcie = (struct pcie_mif *)devm_kzalloc(&pdev->dev, sizeof(struct pcie_mif), GFP_KERNEL); - u16 cmd; - - /* Avoid unused parameter error */ - (void)id; - - if (!pcie) - return NULL; - - pcie_if = &pcie->interface; - - /* initialise interface structure */ - pcie_if->destroy = pcie_mif_destroy; - pcie_if->get_uid = pcie_mif_get_uid; - pcie_if->reset = pcie_mif_reset; - pcie_if->map = pcie_mif_map; - pcie_if->unmap = pcie_mif_unmap; -#ifdef MAILBOX_SETGET - pcie_if->mailbox_set = pcie_mif_mailbox_set; - pcie_if->mailbox_get = pcie_mif_mailbox_get; -#endif - pcie_if->irq_bit_set = pcie_mif_irq_bit_set; - pcie_if->irq_get = pcie_mif_irq_get; - pcie_if->irq_bit_mask_status_get = pcie_mif_irq_bit_mask_status_get; - pcie_if->irq_bit_clear = pcie_mif_irq_bit_clear; - pcie_if->irq_bit_mask = pcie_mif_irq_bit_mask; - pcie_if->irq_bit_unmask = pcie_mif_irq_bit_unmask; - pcie_if->irq_reg_handler = pcie_mif_irq_reg_handler; - pcie_if->irq_unreg_handler = pcie_mif_irq_unreg_handler; - pcie_if->irq_reg_reset_request_handler = pcie_mif_irq_reg_reset_request_handler; - pcie_if->irq_unreg_reset_request_handler = pcie_mif_irq_unreg_reset_request_handler; - pcie_if->get_mbox_ptr = pcie_mif_get_mbox_ptr; - pcie_if->get_mifram_ptr = pcie_mif_get_mifram_ptr; - pcie_if->get_mifram_ref = pcie_mif_get_mifram_ref; - pcie_if->get_mifram_pfn = pcie_mif_get_mif_pfn; - pcie_if->get_mif_device = pcie_mif_get_mif_device; - pcie_if->irq_clear = pcie_mif_irq_clear; - pcie_if->mif_dump_registers = pcie_mif_dump_register; - pcie_if->mif_read_register = NULL; -#ifdef CONFIG_SCSC_QOS - pcie_if->mif_pm_qos_add_request = pcie_mif_pm_qos_add_request; - pcie_if->mif_pm_qos_update_request = pcie_mif_pm_qos_update_request; - pcie_if->mif_pm_qos_remove_request = pcie_mif_pm_qos_remove_request; -#endif - /* Suspend/resume not supported in PCIe MIF */ - pcie_if->suspend_reg_handler = NULL; - pcie_if->suspend_unreg_handler = NULL; - - /* Update state */ - pcie->pdev = pdev; - - pcie->dev = &pdev->dev; - - pcie->r4_handler = pcie_mif_irq_default_handler; - pcie->irq_dev = NULL; - - /* Just do whats is necessary to meet the pci probe - * -BAR0 stuff - * -Interrupt (will be able to handle interrupts?) - */ - - /* My stuff */ - pci_set_drvdata(pdev, pcie); - - rc = pcim_enable_device(pdev); - if (rc) { - SCSC_TAG_ERR_DEV(PCIE_MIF, pcie->dev, - "Error enabling device.\n"); - return NULL; - } - - /* This function returns the flags associated with this resource.*/ - /* esource flags are used to define some features of the individual resource. - * For PCI resources associated with PCI I/O regions, the information is extracted from the base address registers */ - /* IORESOURCE_MEM = If the associated I/O region exists, one and only one of these flags is set */ - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - SCSC_TAG_ERR(PCIE_MIF, "Incorrect BAR configuration\n"); - return NULL; - } - - /* old --- rc = pci_request_regions(pdev, "foo"); */ - /* Request and iomap regions specified by @mask (0x01 ---> BAR0)*/ - rc = pcim_iomap_regions(pdev, BIT(0), DRV_NAME); - if (rc) { - SCSC_TAG_ERR_DEV(PCIE_MIF, pcie->dev, - "pcim_iomap_regions() failed. Aborting.\n"); - return NULL; - } - - - pci_set_master(pdev); - - /* Access iomap allocation table */ - /* return __iomem * const * */ - pcie->registers = pcim_iomap_table(pdev)[0]; - - /* Set up a single MSI interrupt */ - if (pci_enable_msi(pdev)) { - SCSC_TAG_ERR_DEV(PCIE_MIF, pcie->dev, - "Failed to enable MSI interrupts. Aborting.\n"); - return NULL; - } - rc = devm_request_irq(&pdev->dev, pdev->irq, pcie_mif_isr, 0, - DRV_NAME, pcie); - if (rc) { - SCSC_TAG_ERR_DEV(PCIE_MIF, pcie->dev, - "Failed to register MSI handler. Aborting.\n"); - return NULL; - } - -/* if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - * SCSC_TAG_INFO_DEV(PCIE_MIF, pcie->dev, "DMA mask 64bits.\n"); - * pcie->dma_using_dac = 1; */ - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - SCSC_TAG_INFO_DEV(PCIE_MIF, pcie->dev, "DMA mask 32bits.\n"); - pcie->dma_using_dac = 0; - } else { - SCSC_TAG_ERR_DEV(PCIE_MIF, pcie->dev, "Failed to set DMA mask. Aborting.\n"); - return NULL; - } - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - - /* Make sure Mx is in the reset state */ - pcie_mif_reset(pcie_if, true); - - /* Create debug proc entry */ - pcie_create_proc_dir(pcie); - - return pcie_if; -} - -void pcie_mif_destroy_pcie(struct pci_dev *pdev, struct scsc_mif_abs *interface) -{ - /* Create debug proc entry */ - pcie_remove_proc_dir(); - - pci_disable_device(pdev); -} - -struct pci_dev *pcie_mif_get_pci_dev(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - BUG_ON(!interface || !pcie); - - return pcie->pdev; -} - -struct device *pcie_mif_get_dev(struct scsc_mif_abs *interface) -{ - struct pcie_mif *pcie = pcie_mif_from_mif_abs(interface); - - BUG_ON(!interface || !pcie); - - return pcie->dev; -} - - - -/* Functions for proc entry */ -int pcie_mif_set_bar0_register(struct pcie_mif *pcie, unsigned int value, unsigned int offset) -{ - iowrite32(value, pcie->registers + offset); - mmiowb(); - - return 0; -} - -void pcie_mif_get_bar0(struct pcie_mif *pcie, struct scsc_bar0_reg *bar0) -{ - bar0->NEWMSG = ioread32(pcie->registers + SCSC_PCIE_NEWMSG); - bar0->SIGNATURE = ioread32(pcie->registers + SCSC_PCIE_SIGNATURE); - bar0->OFFSET = ioread32(pcie->registers + SCSC_PCIE_OFFSET); - bar0->RUNEN = ioread32(pcie->registers + SCSC_PCIE_RUNEN); - bar0->DEBUG = ioread32(pcie->registers + SCSC_PCIE_DEBUG); - bar0->AXIWCNT = ioread32(pcie->registers + SCSC_PCIE_AXIWCNT); - bar0->AXIRCNT = ioread32(pcie->registers + SCSC_PCIE_AXIRCNT); - bar0->AXIWADDR = ioread32(pcie->registers + SCSC_PCIE_AXIWADDR); - bar0->AXIRADDR = ioread32(pcie->registers + SCSC_PCIE_AXIRADDR); - bar0->TBD = ioread32(pcie->registers + SCSC_PCIE_TBD); - bar0->AXICTRL = ioread32(pcie->registers + SCSC_PCIE_AXICTRL); - bar0->AXIDATA = ioread32(pcie->registers + SCSC_PCIE_AXIDATA); - bar0->AXIRDBP = ioread32(pcie->registers + SCSC_PCIE_AXIRDBP); - bar0->IFAXIWCNT = ioread32(pcie->registers + SCSC_PCIE_IFAXIWCNT); - bar0->IFAXIRCNT = ioread32(pcie->registers + SCSC_PCIE_IFAXIRCNT); - bar0->IFAXIWADDR = ioread32(pcie->registers + SCSC_PCIE_IFAXIWADDR); - bar0->IFAXIRADDR = ioread32(pcie->registers + SCSC_PCIE_IFAXIRADDR); - bar0->IFAXICTRL = ioread32(pcie->registers + SCSC_PCIE_IFAXICTRL); - bar0->GRST = ioread32(pcie->registers + SCSC_PCIE_GRST); - bar0->AMBA2TRANSAXIWCNT = ioread32(pcie->registers + SCSC_PCIE_AMBA2TRANSAXIWCNT); - bar0->AMBA2TRANSAXIRCNT = ioread32(pcie->registers + SCSC_PCIE_AMBA2TRANSAXIRCNT); - bar0->AMBA2TRANSAXIWADDR = ioread32(pcie->registers + SCSC_PCIE_AMBA2TRANSAXIWADDR); - bar0->AMBA2TRANSAXIRADDR = ioread32(pcie->registers + SCSC_PCIE_AMBA2TRANSAXIRADDR); - bar0->AMBA2TRANSAXICTR = ioread32(pcie->registers + SCSC_PCIE_AMBA2TRANSAXICTR); - bar0->TRANS2PCIEREADALIGNAXIWCNT = ioread32(pcie->registers + SCSC_PCIE_TRANS2PCIEREADALIGNAXIWCNT); - bar0->TRANS2PCIEREADALIGNAXIRCNT = ioread32(pcie->registers + SCSC_PCIE_TRANS2PCIEREADALIGNAXIRCNT); - bar0->TRANS2PCIEREADALIGNAXIWADDR = ioread32(pcie->registers + SCSC_PCIE_TRANS2PCIEREADALIGNAXIWADDR); - bar0->TRANS2PCIEREADALIGNAXIRADDR = ioread32(pcie->registers + SCSC_PCIE_TRANS2PCIEREADALIGNAXIRADDR); - bar0->TRANS2PCIEREADALIGNAXICTRL = ioread32(pcie->registers + SCSC_PCIE_TRANS2PCIEREADALIGNAXICTRL); - bar0->READROUNDTRIPMIN = ioread32(pcie->registers + SCSC_PCIE_READROUNDTRIPMIN); - bar0->READROUNDTRIPMAX = ioread32(pcie->registers + SCSC_PCIE_READROUNDTRIPMAX); - bar0->READROUNDTRIPLAST = ioread32(pcie->registers + SCSC_PCIE_READROUNDTRIPLAST); - bar0->CPTAW0 = ioread32(pcie->registers + SCSC_PCIE_CPTAW0); - bar0->CPTAW1 = ioread32(pcie->registers + SCSC_PCIE_CPTAW1); - bar0->CPTAR0 = ioread32(pcie->registers + SCSC_PCIE_CPTAR0); - bar0->CPTAR1 = ioread32(pcie->registers + SCSC_PCIE_CPTAR1); - bar0->CPTB0 = ioread32(pcie->registers + SCSC_PCIE_CPTB0); - bar0->CPTW0 = ioread32(pcie->registers + SCSC_PCIE_CPTW0); - bar0->CPTW1 = ioread32(pcie->registers + SCSC_PCIE_CPTW1); - bar0->CPTW2 = ioread32(pcie->registers + SCSC_PCIE_CPTW2); - bar0->CPTR0 = ioread32(pcie->registers + SCSC_PCIE_CPTR0); - bar0->CPTR1 = ioread32(pcie->registers + SCSC_PCIE_CPTR1); - bar0->CPTR2 = ioread32(pcie->registers + SCSC_PCIE_CPTR2); - bar0->CPTRES = ioread32(pcie->registers + SCSC_PCIE_CPTRES); - bar0->CPTAWDELAY = ioread32(pcie->registers + SCSC_PCIE_CPTAWDELAY); - bar0->CPTARDELAY = ioread32(pcie->registers + SCSC_PCIE_CPTARDELAY); - bar0->CPTSRTADDR = ioread32(pcie->registers + SCSC_PCIE_CPTSRTADDR); - bar0->CPTENDADDR = ioread32(pcie->registers + SCSC_PCIE_CPTENDADDR); - bar0->CPTSZLTHID = ioread32(pcie->registers + SCSC_PCIE_CPTSZLTHID); - bar0->CPTPHSEL = ioread32(pcie->registers + SCSC_PCIE_CPTPHSEL); - bar0->CPTRUN = ioread32(pcie->registers + SCSC_PCIE_CPTRUN); - bar0->FPGAVER = ioread32(pcie->registers + SCSC_PCIE_FPGAVER); -} diff --git a/drivers/misc/samsung/scsc/pcie_mif.h b/drivers/misc/samsung/scsc/pcie_mif.h deleted file mode 100644 index f213c928801d..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mif.h +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved -* -****************************************************************************/ - -#ifndef __PCIE_MIF_H -#define __PCIE_MIF_H -#include -#include "scsc_mif_abs.h" - -#ifdef CONDOR -#define FPGA_OFFSET 0xb8000000 -#else -#define FPGA_OFFSET 0x80000000 -#endif - -#define SCSC_PCIE_MAGIC_VAL 0xdeadbeef - -#define SCSC_PCIE_GRST_OFFSET 0x48 - -/* BAR0 Registers [PCIeBridgeBAR0Regs.doc] */ -#define SCSC_PCIE_NEWMSG 0x0 -#define SCSC_PCIE_SIGNATURE 0x4 -#define SCSC_PCIE_OFFSET 0x8 -#define SCSC_PCIE_RUNEN 0xC -#define SCSC_PCIE_DEBUG 0x10 -#define SCSC_PCIE_AXIWCNT 0x14 -#define SCSC_PCIE_AXIRCNT 0x18 -#define SCSC_PCIE_AXIWADDR 0x1C -#define SCSC_PCIE_AXIRADDR 0x20 -#define SCSC_PCIE_TBD 0x24 -#define SCSC_PCIE_AXICTRL 0x28 -#define SCSC_PCIE_AXIDATA 0x2C -#define SCSC_PCIE_AXIRDBP 0x30 -#define SCSC_PCIE_IFAXIWCNT 0x34 -#define SCSC_PCIE_IFAXIRCNT 0x38 -#define SCSC_PCIE_IFAXIWADDR 0x3C -#define SCSC_PCIE_IFAXIRADDR 0x40 -#define SCSC_PCIE_IFAXICTRL 0x44 -#define SCSC_PCIE_GRST 0x48 -#define SCSC_PCIE_AMBA2TRANSAXIWCNT 0x4C -#define SCSC_PCIE_AMBA2TRANSAXIRCNT 0x50 -#define SCSC_PCIE_AMBA2TRANSAXIWADDR 0x54 -#define SCSC_PCIE_AMBA2TRANSAXIRADDR 0x58 -#define SCSC_PCIE_AMBA2TRANSAXICTR 0x5C -#define SCSC_PCIE_TRANS2PCIEREADALIGNAXIWCNT 0x60 -#define SCSC_PCIE_TRANS2PCIEREADALIGNAXIRCNT 0x64 -#define SCSC_PCIE_TRANS2PCIEREADALIGNAXIWADDR 0x68 -#define SCSC_PCIE_TRANS2PCIEREADALIGNAXIRADDR 0x6C -#define SCSC_PCIE_TRANS2PCIEREADALIGNAXICTRL 0x70 -#define SCSC_PCIE_READROUNDTRIPMIN 0x74 -#define SCSC_PCIE_READROUNDTRIPMAX 0x78 -#define SCSC_PCIE_READROUNDTRIPLAST 0x7C -#define SCSC_PCIE_CPTAW0 0x80 -#define SCSC_PCIE_CPTAW1 0x84 -#define SCSC_PCIE_CPTAR0 0x88 -#define SCSC_PCIE_CPTAR1 0x8C -#define SCSC_PCIE_CPTB0 0x90 -#define SCSC_PCIE_CPTW0 0x94 -#define SCSC_PCIE_CPTW1 0x98 -#define SCSC_PCIE_CPTW2 0x9C -#define SCSC_PCIE_CPTR0 0xA0 -#define SCSC_PCIE_CPTR1 0xA4 -#define SCSC_PCIE_CPTR2 0xA8 -#define SCSC_PCIE_CPTRES 0xAC -#define SCSC_PCIE_CPTAWDELAY 0xB0 -#define SCSC_PCIE_CPTARDELAY 0xB4 -#define SCSC_PCIE_CPTSRTADDR 0xB8 -#define SCSC_PCIE_CPTENDADDR 0xBC -#define SCSC_PCIE_CPTSZLTHID 0xC0 -#define SCSC_PCIE_CPTPHSEL 0xC4 -#define SCSC_PCIE_CPTRUN 0xC8 -#define SCSC_PCIE_FPGAVER 0xCC - -/* from mx141 */ -#define SCSC_PCIE_NEWMSG2 0xD0 -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT -#define SCSC_PCIE_NEWMSG3 0xD4 -#endif - -struct scsc_bar0_reg { - u32 NEWMSG; - u32 SIGNATURE; - u32 OFFSET; - u32 RUNEN; - u32 DEBUG; - u32 AXIWCNT; - u32 AXIRCNT; - u32 AXIWADDR; - u32 AXIRADDR; - u32 TBD; - u32 AXICTRL; - u32 AXIDATA; - u32 AXIRDBP; - u32 IFAXIWCNT; - u32 IFAXIRCNT; - u32 IFAXIWADDR; - u32 IFAXIRADDR; - u32 IFAXICTRL; - u32 GRST; - u32 AMBA2TRANSAXIWCNT; - u32 AMBA2TRANSAXIRCNT; - u32 AMBA2TRANSAXIWADDR; - u32 AMBA2TRANSAXIRADDR; - u32 AMBA2TRANSAXICTR; - u32 TRANS2PCIEREADALIGNAXIWCNT; - u32 TRANS2PCIEREADALIGNAXIRCNT; - u32 TRANS2PCIEREADALIGNAXIWADDR; - u32 TRANS2PCIEREADALIGNAXIRADDR; - u32 TRANS2PCIEREADALIGNAXICTRL; - u32 READROUNDTRIPMIN; - u32 READROUNDTRIPMAX; - u32 READROUNDTRIPLAST; - u32 CPTAW0; - u32 CPTAW1; - u32 CPTAR0; - u32 CPTAR1; - u32 CPTB0; - u32 CPTW0; - u32 CPTW1; - u32 CPTW2; - u32 CPTR0; - u32 CPTR1; - u32 CPTR2; - u32 CPTRES; - u32 CPTAWDELAY; - u32 CPTARDELAY; - u32 CPTSRTADDR; - u32 CPTENDADDR; - u32 CPTSZLTHID; - u32 CPTPHSEL; - u32 CPTRUN; - u32 FPGAVER; - - /* from mx141 */ - u32 NEWMSG2; -}; - -struct scsc_mif_abs *pcie_mif_create(struct pci_dev *pdev, const struct pci_device_id *id); -void pcie_mif_destroy_pcie(struct pci_dev *pdev, struct scsc_mif_abs *interface); -struct pci_dev *pcie_mif_get_pci_dev(struct scsc_mif_abs *interface); -struct device *pcie_mif_get_dev(struct scsc_mif_abs *interface); - -struct pcie_mif; - -void pcie_mif_get_bar0(struct pcie_mif *pcie, struct scsc_bar0_reg *bar0); -int pcie_mif_set_bar0_register(struct pcie_mif *pcie, unsigned int value, unsigned int offset); - -#endif diff --git a/drivers/misc/samsung/scsc/pcie_mif_module.c b/drivers/misc/samsung/scsc/pcie_mif_module.c deleted file mode 100644 index bc8c61d23316..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mif_module.c +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include -#include -#include -#include -#include "pcie_mif_module.h" -#include "pcie_mif.h" - -/* Implements */ -#include "scsc_mif_abs.h" - -struct mif_abs_node { - struct list_head list; - struct scsc_mif_abs *mif_abs; -}; - -struct mif_driver_node { - struct list_head list; - struct scsc_mif_abs_driver *driver; /* list of drivers (in practice just the core_module) */ -}; - -struct mif_mmap_node { - struct list_head list; - struct scsc_mif_mmap_driver *driver; /* list of drivers (in practive just the core_module) */ -}; - -static struct pcie_mif_module { - struct list_head mif_abs_list; - struct list_head mif_driver_list; - struct list_head mif_mmap_list; -} mif_module = { - .mif_abs_list = LIST_HEAD_INIT(mif_module.mif_abs_list), - .mif_driver_list = LIST_HEAD_INIT(mif_module.mif_driver_list), - .mif_mmap_list = LIST_HEAD_INIT(mif_module.mif_mmap_list), -}; - - -static const struct pci_device_id pcie_mif_module_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_SAMSUNG_SCSC) }, - { /*End: all zeroes */ } -}; - -MODULE_DEVICE_TABLE(pci, pcie_mif_module_tbl); - -static void pcie_mif_module_probe_registered_clients(struct scsc_mif_abs *mif_abs) -{ - struct mif_driver_node *mif_driver_node, *next; - struct device *dev; - bool driver_registered = false; - - /* Traverse Linked List for each mif_driver node */ - list_for_each_entry_safe(mif_driver_node, next, &mif_module.mif_driver_list, list) { - SCSC_TAG_INFO(PCIE_MIF, "node %p\n", mif_driver_node); - - dev = pcie_mif_get_dev(mif_abs); - mif_driver_node->driver->probe(mif_driver_node->driver, mif_abs); - driver_registered = true; - } - if (driver_registered == false) - SCSC_TAG_INFO(PCIE_MIF, "No mif drivers registered\n"); -} - -static int pcie_mif_module_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct mif_abs_node *mif_node; - struct scsc_mif_abs *mif_abs; - - mif_node = kzalloc(sizeof(*mif_node), GFP_KERNEL); - if (!mif_node) - return -ENODEV; - - mif_abs = pcie_mif_create(pdev, id); - if (!mif_abs) { - SCSC_TAG_INFO(PCIE_MIF, "Error creating PCIe interface\n"); - kfree(mif_node); - return -ENODEV; - } - /* Add node */ - mif_node->mif_abs = mif_abs; - SCSC_TAG_INFO(PCIE_MIF, "mif_node A %p\n", mif_node); - list_add_tail(&mif_node->list, &mif_module.mif_abs_list); - - pcie_mif_module_probe_registered_clients(mif_abs); - - return 0; -} - -static void pcie_mif_module_remove(struct pci_dev *pdev) -{ - struct mif_abs_node *mif_node, *next; - bool match = false; - - /* Remove node */ - list_for_each_entry_safe(mif_node, next, &mif_module.mif_abs_list, list) { - if (pcie_mif_get_pci_dev(mif_node->mif_abs) == pdev) { - match = true; - SCSC_TAG_INFO(PCIE_MIF, "Match, destroy pcie_mif\n"); - pcie_mif_destroy_pcie(pdev, mif_node->mif_abs); - list_del(&mif_node->list); - kfree(mif_node); - } - } - if (match == false) - SCSC_TAG_INFO(PCIE_MIF, "FATAL, no match for given scsc_mif_abs\n"); -} - -static struct pci_driver scsc_pcie = { - .name = DRV_NAME, - .id_table = pcie_mif_module_tbl, - .probe = pcie_mif_module_probe, - .remove = pcie_mif_module_remove, -}; - -void scsc_mif_abs_register(struct scsc_mif_abs_driver *driver) -{ - struct mif_driver_node *mif_driver_node; - struct mif_abs_node *mif_node; - struct device *dev; - - /* Add node in driver linked list */ - mif_driver_node = kzalloc(sizeof(*mif_driver_node), GFP_KERNEL); - if (!mif_driver_node) - return; - - mif_driver_node->driver = driver; - list_add_tail(&mif_driver_node->list, &mif_module.mif_driver_list); - - /* Traverse Linked List for each mif_abs node */ - list_for_each_entry(mif_node, &mif_module.mif_abs_list, list) { - dev = pcie_mif_get_dev(mif_node->mif_abs); - driver->probe(driver, mif_node->mif_abs); - } -} -EXPORT_SYMBOL(scsc_mif_abs_register); - -void scsc_mif_abs_unregister(struct scsc_mif_abs_driver *driver) -{ - struct mif_driver_node *mif_driver_node, *next; - - /* Traverse Linked List for each mif_driver node */ - list_for_each_entry_safe(mif_driver_node, next, &mif_module.mif_driver_list, list) { - if (mif_driver_node->driver == driver) { - list_del(&mif_driver_node->list); - kfree(mif_driver_node); - } - } -} -EXPORT_SYMBOL(scsc_mif_abs_unregister); - -/* Register a mmap - debug driver - for this specific transport*/ -void scsc_mif_mmap_register(struct scsc_mif_mmap_driver *mmap_driver) -{ - struct mif_mmap_node *mif_mmap_node; - struct mif_abs_node *mif_node; - - /* Add node in driver linked list */ - mif_mmap_node = kzalloc(sizeof(*mif_mmap_node), GFP_KERNEL); - if (!mif_mmap_node) - return; - - mif_mmap_node->driver = mmap_driver; - list_add_tail(&mif_mmap_node->list, &mif_module.mif_mmap_list); - - /* Traverse Linked List for each mif_abs node */ - list_for_each_entry(mif_node, &mif_module.mif_abs_list, list) { - mmap_driver->probe(mmap_driver, mif_node->mif_abs); - } -} -EXPORT_SYMBOL(scsc_mif_mmap_register); - -/* Unregister a mmap - debug driver - for this specific transport*/ -void scsc_mif_mmap_unregister(struct scsc_mif_mmap_driver *mmap_driver) -{ - struct mif_mmap_node *mif_mmap_node, *next; - - /* Traverse Linked List for each mif_mmap_driver node */ - list_for_each_entry_safe(mif_mmap_node, next, &mif_module.mif_mmap_list, list) { - if (mif_mmap_node->driver == mmap_driver) { - list_del(&mif_mmap_node->list); - kfree(mif_mmap_node); - } - } -} -EXPORT_SYMBOL(scsc_mif_mmap_unregister); - -module_pci_driver(scsc_pcie); - -MODULE_DESCRIPTION("SLSI PCIe mx140 MIF abstraction"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/samsung/scsc/pcie_mif_module.h b/drivers/misc/samsung/scsc/pcie_mif_module.h deleted file mode 100644 index 30b1dfcde022..000000000000 --- a/drivers/misc/samsung/scsc/pcie_mif_module.h +++ /dev/null @@ -1,29 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "pcie_mbox_shared_data_defs.h" - -#define PCI_DEVICE_ID_SAMSUNG_SCSC 0x7011 -#define DRV_NAME "scscPCIe" - -/* Max amount of memory allocated by dma_alloc_coherent */ -#define PCIE_MIF_PREALLOC_MEM (4 * 1024 * 1024) -/* Allocatable memory for upper layers */ -/* This value should take into account PCIE_MIF_PREALLOC_MEM - mbox/register - * emulation - peterson mutex ex: */ -/* -------------------- PCIE_MIF_PREALLOC_MEM - | scsc_mbox_s | - | -------------------- - | peterson_m | - | -------------------- - | /////////////// | - | ------------------- PCIE_MIF_ALLOC_MEM - | alloc memory | - | | - | | - | -------------------- - */ -#define PCIE_MIF_ALLOC_MEM ((PCIE_MIF_PREALLOC_MEM) - (PCIE_MIF_MBOX_RESERVED_LEN)) diff --git a/drivers/misc/samsung/scsc/pcie_proc.c b/drivers/misc/samsung/scsc/pcie_proc.c deleted file mode 100644 index a2c7c993ea43..000000000000 --- a/drivers/misc/samsung/scsc/pcie_proc.c +++ /dev/null @@ -1,278 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include "pcie_proc.h" -#include "pcie_mif.h" - -static struct proc_dir_entry *procfs_dir; -static bool pcie_val; - -/* singleton */ -struct pcie_mif *pcie_global; - -static int pcie_procfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = PCIE_PDE_DATA(inode); - return 0; -} - -PCIE_PROCFS_RW_FILE_OPS(pcie_trg); -PCIE_PROCFS_SEQ_FILE_OPS(pcie_dbg); - -static ssize_t pcie_procfs_pcie_trg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "%d\n", (pcie_val ? 1 : 0)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -#define ROW 52 -#define COL 2 -char *lookup_regs[ROW][COL] = { - { "NEWMSG", "0" }, - { "SIGNATURE", "4" }, - { "OFFSET", "8" }, - { "RUNEN", "12" }, - { "DEBUG", "16" }, - { "AXIWCNT", "20" }, - { "AXIRCNT", "24" }, - { "AXIWADDR", "28" }, - { "AXIRADDR", "32" }, - { "TBD", "36" }, - { "AXICTRL", "40" }, - { "AXIDATA", "44" }, - { "AXIRDBP", "48" }, - { "IFAXIWCNT", "52" }, - { "IFAXIRCNT", "56" }, - { "IFAXIWADDR", "60" }, - { "IFAXIRADDR", "64" }, - { "IFAXICTRL", "68" }, - { "GRST", "72" }, - { "AMBA2TRANSAXIWCNT", "76" }, - { "AMBA2TRANSAXIRCNT", "80" }, - { "AMBA2TRANSAXIWADDR", "84" }, - { "AMBA2TRANSAXIRADDR", "88" }, - { "AMBA2TRANSAXICTR", "92" }, - { "TRANS2PCIEREADALIGNAXIWCNT", "96" }, - { "TRANS2PCIEREADALIGNAXIRCNT", "100" }, - { "TRANS2PCIEREADALIGNAXIWADDR", "104" }, - { "TRANS2PCIEREADALIGNAXIRADDR", "108" }, - { "TRANS2PCIEREADALIGNAXICTRL", "112" }, - { "READROUNDTRIPMIN", "116" }, - { "READROUNDTRIPMAX", "120" }, - { "READROUNDTRIPLAST", "124" }, - { "CPTAW0", "128" }, - { "CPTAW1", "132" }, - { "CPTAR0", "136" }, - { "CPTAR1", "140" }, - { "CPTB0", "144" }, - { "CPTW0", "148" }, - { "CPTW1", "152" }, - { "CPTW2", "156" }, - { "CPTR0", "160" }, - { "CPTR1", "164" }, - { "CPTR2", "168" }, - { "CPTRES", "172" }, - { "CPTAWDELAY", "176" }, - { "CPTARDELAY", "180" }, - { "CPTSRTADDR", "184" }, - { "CPTENDADDR", "188" }, - { "CPTSZLTHID", "192" }, - { "CPTPHSEL", "196" }, - { "CPTRUN", "200" }, - { "FPGAVER", "204" }, -}; - -/* Trigger boot of Curator over SDIO without Chip Power Manager present */ -static ssize_t pcie_procfs_pcie_trg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - char *sptr, *token; - unsigned int len = 0, pass = 0; - u32 value = 0; - int i = 0; - int rc; - - int match = 0, offset = 0; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - sptr = buf; - - while ((token = strsep(&sptr, " ")) != NULL) { - switch (pass) { - /* register */ - case 0: - SCSC_TAG_INFO(PCIE_MIF, "str %s\n", lookup_regs[0][0]); - SCSC_TAG_INFO(PCIE_MIF, "token %s\n", token); - SCSC_TAG_INFO(PCIE_MIF, "len %d\n", len); - for (i = 0; i < ROW; i++) - if (!strncmp(lookup_regs[i][0], token, len)) { - rc = kstrtou32(lookup_regs[i][1], 0, &offset); - if (rc) - match = 0; - else - match = 1; - break; - } - - if (!match) { - SCSC_TAG_INFO(PCIE_MIF, "Register %s not Found!!\n", token); - SCSC_TAG_INFO(PCIE_MIF, "Type 'cat /proc/driver/pcie_ctrl/pcie_dbg' to get register names\n"); - } - break; - /* value */ - case 1: - if ((token[0] == '0') && (token[1] == 'x')) { - if (kstrtou32(token, 16, &value)) { - SCSC_TAG_INFO(PCIE_MIF, "Incorrect format,,,address should start by 0x\n"); - SCSC_TAG_INFO(PCIE_MIF, "Example: \"0xaaaabbbb 256 8\"\n"); - goto error; - } - } else { - SCSC_TAG_INFO(PCIE_MIF, "Incorrect format,,,address should start by 0x\n"); - SCSC_TAG_INFO(PCIE_MIF, "Example: \"0xaaaabbbb 256 8\"\n"); - goto error; - } - break; - } - pass++; - } - if (pass != 2 && !match) { - SCSC_TAG_INFO(PCIE_MIF, "Wrong format: \n"); - SCSC_TAG_INFO(PCIE_MIF, "Example: \"DEBUGADDR 0xaaaabbbb\"\n"); - goto error; - } - SCSC_TAG_INFO(PCIE_MIF, "Setting value 0x%x to register %s offset %d\n", value, lookup_regs[i][0], offset); - pcie_mif_set_bar0_register(pcie_global, value, offset); -error: - return count; -} - -static int pcie_procfs_pcie_dbg_show(struct seq_file *m, void *v) -{ - struct scsc_bar0_reg bar0; - - if (!pcie_global) { - seq_puts(m, "endpoint not registered"); - return 0; - } - - pcie_mif_get_bar0(pcie_global, &bar0); - - seq_puts(m, "\n---------BAR0---------\n"); - - seq_printf(m, "NEWMSG 0x%08X\n", bar0.NEWMSG); - seq_printf(m, "SIGNATURE 0x%08X\n", bar0.SIGNATURE); - seq_printf(m, "OFFSET 0x%08X\n", bar0.OFFSET); - seq_printf(m, "RUNEN 0x%08X\n", bar0.RUNEN); - seq_printf(m, "DEBUG 0x%08X\n", bar0.DEBUG); - seq_printf(m, "AXIWCNT 0x%08X\n", bar0.AXIWCNT); - seq_printf(m, "AXIRCNT 0x%08X\n", bar0.AXIRCNT); - seq_printf(m, "AXIWADDR 0x%08X\n", bar0.AXIWADDR); - seq_printf(m, "AXIRADDR 0x%08X\n", bar0.AXIRADDR); - seq_printf(m, "TBD 0x%08X\n", bar0.TBD); - seq_printf(m, "AXICTRL 0x%08X\n", bar0.AXICTRL); - seq_printf(m, "AXIDATA 0x%08X\n", bar0.AXIDATA); - seq_printf(m, "AXIRDBP 0x%08X\n", bar0.AXIRDBP); - seq_printf(m, "IFAXIWCNT 0x%08X\n", bar0.IFAXIWCNT); - seq_printf(m, "IFAXIRCNT 0x%08X\n", bar0.IFAXIRCNT); - seq_printf(m, "IFAXIWADDR 0x%08X\n", bar0.IFAXIWADDR); - seq_printf(m, "IFAXIRADDR 0x%08X\n", bar0.IFAXIRADDR); - seq_printf(m, "IFAXICTRL 0x%08X\n", bar0.IFAXICTRL); - seq_printf(m, "GRST 0x%08X\n", bar0.GRST); - seq_printf(m, "AMBA2TRANSAXIWCNT 0x%08X\n", bar0.AMBA2TRANSAXIWCNT); - seq_printf(m, "AMBA2TRANSAXIRCNT 0x%08X\n", bar0.AMBA2TRANSAXIRCNT); - seq_printf(m, "AMBA2TRANSAXIWADDR 0x%08X\n", bar0.AMBA2TRANSAXIWADDR); - seq_printf(m, "AMBA2TRANSAXIRADDR 0x%08X\n", bar0.AMBA2TRANSAXIRADDR); - seq_printf(m, "AMBA2TRANSAXICTR 0x%08X\n", bar0.AMBA2TRANSAXICTR); - seq_printf(m, "TRANS2PCIEREADALIGNAXIWCNT 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIWCNT); - seq_printf(m, "TRANS2PCIEREADALIGNAXIRCNT 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIRCNT); - seq_printf(m, "TRANS2PCIEREADALIGNAXIWADDR 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIWADDR); - seq_printf(m, "TRANS2PCIEREADALIGNAXIRADDR 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIRADDR); - seq_printf(m, "TRANS2PCIEREADALIGNAXICTRL 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXICTRL); - seq_printf(m, "READROUNDTRIPMIN 0x%08X\n", bar0.READROUNDTRIPMIN); - seq_printf(m, "READROUNDTRIPMAX 0x%08X\n", bar0.READROUNDTRIPMAX); - seq_printf(m, "READROUNDTRIPLAST 0x%08X\n", bar0.READROUNDTRIPLAST); - seq_printf(m, "CPTAW0 0x%08X\n", bar0.CPTAW0); - seq_printf(m, "CPTAW1 0x%08X\n", bar0.CPTAW1); - seq_printf(m, "CPTAR0 0x%08X\n", bar0.CPTAR0); - seq_printf(m, "CPTAR1 0x%08X\n", bar0.CPTAR1); - seq_printf(m, "CPTB0 0x%08X\n", bar0.CPTB0); - seq_printf(m, "CPTW0 0x%08X\n", bar0.CPTW0); - seq_printf(m, "CPTW1 0x%08X\n", bar0.CPTW1); - seq_printf(m, "CPTW2 0x%08X\n", bar0.CPTW2); - seq_printf(m, "CPTR0 0x%08X\n", bar0.CPTR0); - seq_printf(m, "CPTR1 0x%08X\n", bar0.CPTR1); - seq_printf(m, "CPTR2 0x%08X\n", bar0.CPTR2); - seq_printf(m, "CPTRES 0x%08X\n", bar0.CPTRES); - seq_printf(m, "CPTAWDELAY 0x%08X\n", bar0.CPTAWDELAY); - seq_printf(m, "CPTARDELAY 0x%08X\n", bar0.CPTARDELAY); - seq_printf(m, "CPTSRTADDR 0x%08X\n", bar0.CPTSRTADDR); - seq_printf(m, "CPTENDADDR 0x%08X\n", bar0.CPTENDADDR); - seq_printf(m, "CPTSZLTHID 0x%08X\n", bar0.CPTSZLTHID); - seq_printf(m, "CPTPHSEL 0x%08X\n", bar0.CPTPHSEL); - seq_printf(m, "CPTRUN 0x%08X\n", bar0.CPTRUN); - seq_printf(m, "FPGAVER 0x%08X\n", bar0.FPGAVER); - return 0; -} - -static const char *procdir = "driver/pcie_ctrl"; - -#define PCIE_DIRLEN 128 - - -int pcie_create_proc_dir(struct pcie_mif *pcie) -{ - char dir[PCIE_DIRLEN]; - struct proc_dir_entry *parent; - - (void)snprintf(dir, sizeof(dir), "%s", procdir); - parent = proc_mkdir(dir, NULL); - if (parent) { -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = NULL; -#endif - procfs_dir = parent; - PCIE_PROCFS_ADD_FILE(NULL, pcie_trg, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - PCIE_PROCFS_SEQ_ADD_FILE(NULL, pcie_dbg, parent, S_IRUSR | S_IRGRP | S_IROTH); - } else { - SCSC_TAG_INFO(PCIE_MIF, "failed to create /proc dir\n"); - return -EINVAL; - } - - pcie_global = pcie; - - return 0; - -err: - return -EINVAL; -} - -void pcie_remove_proc_dir(void) -{ - if (procfs_dir) { - char dir[PCIE_DIRLEN]; - - PCIE_PROCFS_REMOVE_FILE(pcie_trg, procfs_dir); - PCIE_PROCFS_REMOVE_FILE(pcie_dbg, procfs_dir); - - (void)snprintf(dir, sizeof(dir), "%s", procdir); - remove_proc_entry(dir, NULL); - procfs_dir = NULL; - } - - pcie_global = NULL; -} diff --git a/drivers/misc/samsung/scsc/pcie_proc.h b/drivers/misc/samsung/scsc/pcie_proc.h deleted file mode 100644 index 77ad2e7fb676..000000000000 --- a/drivers/misc/samsung/scsc/pcie_proc.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* - * Chip Manager /proc interface - */ -#include -#include -#include - -#include "pcie_mif.h" - -#ifndef SCSC_PCIE_PROC_H -#define SCSC_PCIE_PROC_H - -#ifndef AID_WIFI -#define AID_WIFI 0444 -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define PCIE_PDE_DATA(inode) PDE_DATA(inode) -#else -#define PCIE_PDE_DATA(inode) (PDE(inode)->data) -#endif - -#define PCIE_PROCFS_SEQ_FILE_OPS(name) \ - static int pcie_procfs_ ## name ## _show(struct seq_file *m, void *v); \ - static int pcie_procfs_ ## name ## _open(struct inode *inode, struct file *file) \ - { \ - return single_open(file, pcie_procfs_ ## name ## _show, PCIE_PDE_DATA(inode)); \ - } \ - static const struct file_operations pcie_procfs_ ## name ## _fops = { \ - .open = pcie_procfs_ ## name ## _open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - } - -#define PCIE_PROCFS_SEQ_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = proc_create_data(# name, mode, parent, &pcie_procfs_ ## name ## _fops, _sdev); \ - if (!entry) { \ - goto err; \ - } \ - PCIE_PROCFS_SET_UID_GID(entry); \ - } while (0) - -#define PCIE_PROCFS_RW_FILE_OPS(name) \ - static ssize_t pcie_procfs_ ## name ## _write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); \ - static ssize_t pcie_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations pcie_procfs_ ## name ## _fops = { \ - .read = pcie_procfs_ ## name ## _read, \ - .write = pcie_procfs_ ## name ## _write, \ - .open = pcie_procfs_open_file_generic, \ - .llseek = generic_file_llseek \ - } - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define PCIE_PROCFS_SET_UID_GID(_entry) \ - do { \ - kuid_t proc_kuid = KUIDT_INIT(AID_WIFI); \ - kgid_t proc_kgid = KGIDT_INIT(AID_WIFI); \ - proc_set_user(_entry, proc_kuid, proc_kgid); \ - } while (0) -#else -#define PCIE_PROCFS_SET_UID_GID(entry) \ - do { \ - (entry)->uid = AID_WIFI; \ - (entry)->gid = AID_WIFI; \ - } while (0) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define PCIE_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry = proc_create_data(# name, mode, parent, &pcie_procfs_ ## name ## _fops, _sdev); \ - PCIE_PROCFS_SET_UID_GID(entry); \ - } while (0) -#else -#define PCIE_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = create_proc_entry(# name, mode, parent); \ - if (entry) { \ - entry->proc_fops = &pcie_procfs_ ## name ## _fops; \ - entry->data = _sdev; \ - PCIE_PROCFS_SET_UID_GID(entry); \ - } \ - } while (0) -#endif - -#define PCIE_PROCFS_REMOVE_FILE(name, parent) remove_proc_entry(# name, parent) - -int pcie_create_proc_dir(struct pcie_mif *pcie); -void pcie_remove_proc_dir(void); - -#endif /* SCSC_PCIE_PROC_H */ diff --git a/drivers/misc/samsung/scsc/peterson_mutex.h b/drivers/misc/samsung/scsc/peterson_mutex.h deleted file mode 100644 index 7f24332c1331..000000000000 --- a/drivers/misc/samsung/scsc/peterson_mutex.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SCSC_PETERSON_H -#define __SCSC_PETERSON_H - -#include -#include "mif_reg.h" - -#define R4_PROCESS 0 -#define AP_PROCESS 1 -#define DELAY_NS 100 /* delay in ns*/ - -static inline void peterson_mutex_init(struct peterson_mutex *p_mutex) -{ - if (!p_mutex) { - pr_info("Mutex not declared\n"); - return; - } - - p_mutex->flag[0] = false; - p_mutex->flag[1] = false; - p_mutex->turn = 0; -} - -static inline void peterson_mutex_lock(struct peterson_mutex *p_mutex, unsigned int process) -{ - unsigned int other = 1 - process; - - p_mutex->flag[process] = true; - /* write barrier */ - smp_wmb(); - p_mutex->turn = other; - /* write barrier */ - smp_wmb(); - - while ((p_mutex->flag[other]) && (p_mutex->turn == other)) - ndelay(DELAY_NS); -} - -static inline void peterson_mutex_unlock(struct peterson_mutex *p_mutex, unsigned int process) -{ - p_mutex->flag[process] = false; - /* write barrier */ - smp_wmb(); -} -#endif diff --git a/drivers/misc/samsung/scsc/platform_mif.c b/drivers/misc/samsung/scsc/platform_mif.c deleted file mode 100755 index e2e0217388d6..000000000000 --- a/drivers/misc/samsung/scsc/platform_mif.c +++ /dev/null @@ -1,2524 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Implements interface */ - -#include "platform_mif.h" - -/* Interfaces it Uses */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef CONFIG_SOC_EXYNOS7570 -#include -#endif -#ifdef CONFIG_OF -#include -#include -#include -#endif -#include -#include -#include -#include -#ifdef CONFIG_SOC_EXYNOS7570 -#include "mif_reg.h" -#elif defined(CONFIG_SOC_EXYNOS7872) -#include "mif_reg_S5E7872.h" -#elif defined(CONFIG_SOC_EXYNOS7885) -#include "mif_reg_S5E7885.h" -#elif defined(CONFIG_SOC_EXYNOS9610) -#include "mif_reg_S5E9610.h" -#endif -#include "platform_mif_module.h" -#ifdef CONFIG_ARCH_EXYNOS -#include -#endif - -#ifdef CONFIG_SCSC_SMAPPER -#include -#include "mif_reg_smapper.h" -#endif -#ifdef CONFIG_SCSC_QOS -#include -#endif - -#if !defined(CONFIG_SOC_EXYNOS7872) && !defined(CONFIG_SOC_EXYNOS7570) \ - && !defined(CONFIG_SOC_EXYNOS7885) && !defined(CONFIG_SOC_EXYNOS9610) && !defined(CONFIG_SOC_EXYNOS9630) -#error Target processor CONFIG_SOC_EXYNOS7570 or CONFIG_SOC_EXYNOS7872 or CONFIG_SOC_EXYNOS7885 or CONFIG_SOC_EXYNOS9610 not selected -#endif - -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) -/* TODO: this will be put in a header */ -extern int exynos_acpm_set_flag(void); -#endif - -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif -/* Time to wait for CFG_REQ IRQ on 9610 */ -#define WLBT_BOOT_TIMEOUT (HZ) - -#ifdef CONFIG_OF_RESERVED_MEM -#include -#endif -static unsigned long sharedmem_base; -static size_t sharedmem_size; - -#ifdef CONFIG_SCSC_CHV_SUPPORT -static bool chv_disable_irq; -module_param(chv_disable_irq, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(chv_disable_irq, "Do not register for irq"); -#endif - -#ifdef CONFIG_SCSC_GPR4_CON_DEBUG -static u32 reg_bkp; -static bool reg_update; -static void __iomem *gpio_base; -static bool gpr4_debug; -module_param(gpr4_debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(gpr4_debug, "GPR4 PIO muxes switching to the Maxwell. Default = N. Effective on Maxwell power on"); -#endif - -static bool enable_platform_mif_arm_reset = true; -module_param(enable_platform_mif_arm_reset, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_platform_mif_arm_reset, "Enables WIFIBT ARM cores reset"); - -#ifdef CONFIG_SCSC_QOS -struct qos_table { - unsigned int freq_mif; - unsigned int freq_int; - unsigned int freq_cl0; - unsigned int freq_cl1; -}; -#endif - -struct platform_mif { - struct scsc_mif_abs interface; - struct scsc_mbox_s *mbox; - struct platform_device *pdev; - - struct device *dev; - - struct { - int irq_num; - int flags; - atomic_t irq_disabled_cnt; - } wlbt_irq[PLATFORM_MIF_NUM_IRQS]; - - /* MIF registers preserved during suspend */ - struct { - u32 irq_bit_mask; - } mif_preserve; - - /* register MBOX memory space */ - size_t reg_start; - size_t reg_size; - void __iomem *base; - -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - /* register MBOX memory space for M4 */ - size_t reg_start_m4; - size_t reg_size_m4; - void __iomem *base_m4; -#endif - /* register CMU memory space */ - struct regmap *cmu_base; -#ifdef CONFIG_SCSC_CLK20MHZ - u32 usbpll_delay; -#endif - - void __iomem *con0_base; - - /* pmu syscon regmap */ - struct regmap *pmureg; -#if defined(CONFIG_SOC_EXYNOS9610) - struct regmap *baaw_p_wlbt; - struct regmap *dbus_baaw; - struct regmap *pbus_baaw; - struct regmap *wlbt_remap; - struct regmap *boot_cfg; - - /* Signalled when CFG_REQ IRQ handled */ - struct completion cfg_ack; - - /* State of CFG_REQ handler */ - enum wlbt_boot_state { - WLBT_BOOT_IN_RESET = 0, - WLBT_BOOT_WAIT_CFG_REQ, - WLBT_BOOT_CFG_DONE, - WLBT_BOOT_CFG_ERROR - } boot_state; - -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER */ - void __iomem *smapper_base; - u8 smapper_banks; - struct { - u8 bank; - u32 ws; - bool large; - struct scsc_mif_smapper_info bank_info; - } *smapper; -#endif - /* Shared memory space - reserved memory */ - unsigned long mem_start; - size_t mem_size; - void __iomem *mem; - - /* Callback function and dev pointer mif_intr manager handler */ - void (*r4_handler)(int irq, void *data); - void *irq_dev; - /* spinlock to serialize driver access */ - spinlock_t mif_spinlock; - void (*reset_request_handler)(int irq, void *data); - void *irq_reset_request_dev; - -#ifdef CONFIG_SCSC_QOS - /* QoS table */ - struct qos_table *qos; - bool qos_enabled; -#endif - /* Suspend/resume handlers */ - int (*suspend_handler)(struct scsc_mif_abs *abs, void *data); - void (*resume_handler)(struct scsc_mif_abs *abs, void *data); - void *suspendresume_data; -}; - -extern int mx140_log_dump(void); - -#define platform_mif_from_mif_abs(MIF_ABS_PTR) container_of(MIF_ABS_PTR, struct platform_mif, interface) - -#ifdef CONFIG_SCSC_CLK20MHZ -static void __platform_mif_usbpll_claim(struct platform_mif *platform, bool wlbt); -#endif - -inline void platform_mif_reg_write(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->base + offset); -} - -inline u32 platform_mif_reg_read(struct platform_mif *platform, u16 offset) -{ - return readl(platform->base + offset); -} - -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) -inline void platform_mif_reg_write_m4(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->base_m4 + offset); -} - -inline u32 platform_mif_reg_read_m4(struct platform_mif *platform, u16 offset) -{ - return readl(platform->base_m4 + offset); -} -#endif - -#ifdef CONFIG_SCSC_SMAPPER -inline void platform_mif_reg_write_smapper(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->smapper_base + offset); -} - -inline u32 platform_mif_reg_read_smapper(struct platform_mif *platform, u16 offset) -{ - return readl(platform->smapper_base + offset); -} - -#define PLATFORM_MIF_SHIFT_SMAPPER_ADDR 11 /* From 36 bits addres to 25 bits */ -#define PLATFORM_MIF_SHIFT_SMAPPER_END 4 /* End address aligment */ - -/* Platform is responsible to give the phys mapping of the SMAPPER maps */ -static int platform_mif_smapper_get_mapping(struct scsc_mif_abs *interface, u8 *phy_map, u16 *align) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Mapping %d banks\n", platform->smapper_banks); - - if (!platform->smapper_banks) - return -EINVAL; - - for (i = 0; i < platform->smapper_banks; i++) { - if (platform->smapper[i].large) - phy_map[i] = SCSC_MIF_ABS_LARGE_BANK; - else - phy_map[i] = SCSC_MIF_ABS_SMALL_BANK; - } - - if (align) - *align = 1 << PLATFORM_MIF_SHIFT_SMAPPER_ADDR; - - return 0; -} - -static int platform_mif_smapper_get_bank_info(struct scsc_mif_abs *interface, u8 bank, struct scsc_mif_smapper_info *bank_info) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper_banks) - return -EINVAL; - - bank_info->num_entries = platform->smapper[bank].bank_info.num_entries; - bank_info->mem_range_bytes = platform->smapper[bank].bank_info.mem_range_bytes; - - return 0; -} - -static u8 platform_mif_smapper_granularity_to_bits(u32 granularity) -{ - if (granularity <= 2 * 1024) - return 0; - if (granularity <= 4 * 1024) - return 1; - if (granularity <= 8 * 1024) - return 2; - if (granularity <= 16 * 1024) - return 3; - if (granularity <= 32 * 1024) - return 4; - if (granularity <= 64 * 1024) - return 5; - if (granularity <= 128 * 1024) - return 6; - return 7; -} - -static u32 platform_mif_smapper_get_bank_base_address(struct scsc_mif_abs *interface, u8 bank) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper) - return 0; - - return platform->smapper[bank].ws; -} - -/* Configure smapper according the memory map and range */ -static void platform_mif_smapper_configure(struct scsc_mif_abs *interface, u32 granularity) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u8 gran; - u8 nb = platform->smapper_banks; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Configure SMAPPER with granularity %d\n", granularity); - - gran = platform_mif_smapper_granularity_to_bits(granularity); - - platform_mif_reg_write_smapper(platform, SMAPPER_QCH_DISABLE, 1); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AR, 0); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AW, 0); - /* Program SMAPPER memmap */ - for (i = 0; i < nb; i++) { - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(i), 0); - /* Set START_ADDR */ - platform_mif_reg_write_smapper(platform, START_ADDR(i), platform->smapper[i].ws); - /* Set ADDR_GRANULARITY - FIXED AT 4KB */ - platform_mif_reg_write_smapper(platform, ADDR_GRANULARITY(i), gran); - /* WLAN_ADDR_MAP operation is started */ - } - /* Set access window control (MSB 32bits Start/End address) */ - /* Remapped address should be ranged from AW_START_ADDR to AW_EN_ADDR */ - platform_mif_reg_write_smapper(platform, AW_START_ADDR, 0); - platform_mif_reg_write_smapper(platform, AW_END_ADDR, dma_get_mask(platform->dev) >> PLATFORM_MIF_SHIFT_SMAPPER_END); - smp_mb(); -} - -/* Caller is responsible of validating the phys address (alignment) */ -static int platform_mif_smapper_write_sram(struct scsc_mif_abs *interface, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u32 rb; - - if (!platform->smapper_banks) - return -EINVAL; - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "SMAPPER not enabled\n"); - return -EINVAL; - } - - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 0); - /* Write mapping table to SRAM. Each entry consists of 25 bits MSB address to remap */ - for (i = 0; i < num_entries; i++) { - if (!addr[i]) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ADDR IS NULL at bank %d entry %d/%d\n", bank, first_entry + i, num_entries); - return -EINVAL; - } - /* Set SRAM_WRITE_CTRL to 1'b1*/ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 1); - platform_mif_reg_write_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i), addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - /* check incorrect writings */ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 0); - rb = platform_mif_reg_read_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i)); - if (rb != addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "incorrect mapping detected rb 0x%x, addr 0x%x\n", rb, (u32)addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - return -EFAULT; - } - } - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 1); - smp_mb(); - return 0; -} - -static int platform_mif_parse_smapper(struct platform_mif *platform, struct device_node *np, u8 num_banks) -{ - /* SMAPPER parsing */ - struct device_node *np_banks; - char node_name[50]; - u32 val[2]; - u8 i; - u32 bank = 0, ws = 0, wsz = 0, ent = 0, large = 0; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "banks found: %d szof %zu\n", num_banks, sizeof(*platform->smapper)); - - platform->smapper = kmalloc_array(num_banks, sizeof(*platform->smapper), GFP_KERNEL); - - if (!platform->smapper) - return -ENOMEM; - - for (i = 0; i < num_banks; i++) { - snprintf(node_name, sizeof(node_name), "smapper_bank_%d", i); - np_banks = of_find_node_by_name(np, node_name); - if (!np_banks) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "%s: could not find smapper_bank\n", - node_name); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - of_property_read_u32(np_banks, "bank_num", &bank); - of_property_read_u32(np_banks, "fw_window_start", &ws); - of_property_read_u32(np_banks, "fw_window_size", &wsz); - of_property_read_u32(np_banks, "num_entries", &ent); - of_property_read_u32(np_banks, "is_large", &large); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "bank %d fw_w_start 0x%x fw_w_sz 0x%x entries %d is_large %d\n", - bank, ws, wsz, ent, large); - - platform->smapper[i].bank = (u8)bank; - platform->smapper[i].ws = ws; - platform->smapper[i].large = (bool)large; - platform->smapper[i].bank_info.num_entries = ent; - platform->smapper[i].bank_info.mem_range_bytes = wsz; - } - - /* Update the number of banks before returning */ - platform->smapper_banks = num_banks; - - of_property_read_u32_array(np, "smapper_reg", val, 2); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "smapper reg address 0x%x size 0x%x\n", val[0], val[1]); - platform->smapper_base = - devm_ioremap_nocache(platform->dev, val[0], val[1]); - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping smapper register region\n"); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - - return 0; -} -#endif -#ifdef CONFIG_SCSC_QOS -static int platform_mif_parse_qos(struct platform_mif *platform, struct device_node *np) -{ - int len, i; - - platform->qos_enabled = false; - - len = of_property_count_u32_elems(np, "qos_table"); - if (!(len == 12)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "No qos table for wlbt, or incorrect size\n"); - return -ENOENT; - } - - platform->qos = devm_kzalloc(platform->dev, sizeof(struct qos_table) * len / 4, GFP_KERNEL); - if (!platform->qos) - return -ENOMEM; - - of_property_read_u32_array(np, "qos_table", (unsigned int *)platform->qos, len); - - for (i = 0; i < len / 4; i++) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "QoS Table[%d] mif : %u int : %u cl0 : %u cl1: %u\n", i, - platform->qos[i].freq_mif, - platform->qos[i].freq_int, - platform->qos[i].freq_cl0, - platform->qos[i].freq_cl1); - } - - platform->qos_enabled = true; - return 0; -} - -struct qos_table platform_mif_pm_qos_get_table(struct platform_mif *platform, enum scsc_qos_config config) -{ - struct qos_table table; - - switch (config) { - case SCSC_QOS_MIN: - table.freq_mif = platform->qos[0].freq_mif; - table.freq_int = platform->qos[0].freq_int; - table.freq_cl0 = platform->qos[0].freq_cl0; - table.freq_cl1 = platform->qos[0].freq_cl1; - break; - - case SCSC_QOS_MED: - table.freq_mif = platform->qos[1].freq_mif; - table.freq_int = platform->qos[1].freq_int; - table.freq_cl0 = platform->qos[1].freq_cl0; - table.freq_cl1 = platform->qos[1].freq_cl1; - break; - - case SCSC_QOS_MAX: - table.freq_mif = platform->qos[2].freq_mif; - table.freq_int = platform->qos[2].freq_int; - table.freq_cl0 = platform->qos[2].freq_cl0; - table.freq_cl1 = platform->qos[2].freq_cl1; - break; - - default: - table.freq_mif = 0; - table.freq_int = 0; - table.freq_cl0 = 0; - table.freq_cl1 = 0; - } - - return table; -} - -static int platform_mif_pm_qos_add_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS add request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_add_request(&qos_req->pm_qos_req_mif, PM_QOS_BUS_THROUGHPUT, table.freq_mif); - pm_qos_add_request(&qos_req->pm_qos_req_int, PM_QOS_DEVICE_THROUGHPUT, table.freq_int); - pm_qos_add_request(&qos_req->pm_qos_req_cl0, PM_QOS_CLUSTER0_FREQ_MIN, table.freq_cl0); - pm_qos_add_request(&qos_req->pm_qos_req_cl1, PM_QOS_CLUSTER1_FREQ_MIN, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_update_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS update request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_update_request(&qos_req->pm_qos_req_mif, table.freq_mif); - pm_qos_update_request(&qos_req->pm_qos_req_int, table.freq_int); - pm_qos_update_request(&qos_req->pm_qos_req_cl0, table.freq_cl0); - pm_qos_update_request(&qos_req->pm_qos_req_cl1, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_remove_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform) - return -ENODEV; - - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS remove request\n"); - pm_qos_remove_request(&qos_req->pm_qos_req_mif); - pm_qos_remove_request(&qos_req->pm_qos_req_int); - pm_qos_remove_request(&qos_req->pm_qos_req_cl0); - pm_qos_remove_request(&qos_req->pm_qos_req_cl1); - - return 0; -} -#endif - -static void platform_mif_irq_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT handler not registered\n"); -} - -static void platform_mif_irq_reset_request_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT reset_request handler not registered\n"); -} - -irqreturn_t platform_mif_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "INT %pS\n", platform->r4_handler); - if (platform->r4_handler != platform_mif_irq_default_handler) - platform->r4_handler(irq, platform->irq_dev); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MIF Interrupt Handler not registered\n"); - - return IRQ_HANDLED; -} - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ -irqreturn_t platform_alive_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - - return IRQ_HANDLED; -} -#endif - -irqreturn_t platform_wdog_isr(int irq, void *data) -{ - int ret = 0; - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - if (platform->reset_request_handler != platform_mif_irq_reset_request_default_handler) { - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - platform->reset_request_handler(irq, platform->irq_reset_request_dev); - } else { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG Interrupt reset_request_handler not registered\n"); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Disabling unhandled WDOG IRQ.\n"); - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_inc(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt); - } -#ifdef CONFIG_SOC_EXYNOS9610 - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_RESET_REQ_CLR, WLBT_RESET_REQ_CLR); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clearing WLBT_RESET_REQ\n"); - if (ret < 0) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_RESET_REQ_CLR]: %d\n", ret); -#else - ret = regmap_update_bits(platform->pmureg, WIFI_CTRL_NS, - WIFI_RESET_REQ_CLR, WIFI_RESET_REQ_CLR); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clearing WIFI_RESET_REQ\n"); - if (ret < 0) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WIFI_CTRL_NS[WIFI_RESET_REQ_CLR]: %d\n", ret); -#endif - return IRQ_HANDLED; -} - -#ifdef CONFIG_SOC_EXYNOS9610 -/* - * Attached array contains the replacement PMU boot code which should - * be programmed using the CBUS during the config phase. - */ -uint32_t ka_patch[] = { - /* Low temp fix 28/1 - * Maxwell142 PMU+PROC combined boot ROM - * IP Version: 0xA3 - * Major Version: 0xF, Minor Version: 0xF - * PMU ROM version: 0x4 - * PROC ROM version: 0x0 - */ - 0x90750002, - 0x11a4c218, - 0x75671191, - 0x9075e090, - 0x54b3e5e7, - 0x30f76001, - 0xb14315a2, - 0xb4b2e503, - 0xb153fb03, - 0xa90185fc, - 0xacf50774, - 0x75fdadb5, - 0xb47508a0, - 0x54b3e501, - 0x75fa7001, - 0x907500b4, - 0x78cb8018, - 0x80837982, - 0x07a075c5, - 0xb0783779, - 0xb40754e6, - 0x0b800207, - 0xc404f6d9, - 0xaf7590f5, - 0x75038000, - 0x53229090, - 0xce53eff7, - 0xd90479fe, - 0xfdce53fe, - 0xfed90c79, - 0x75fbce53, - 0x91530b92, - 0xf7ce53fd, - 0x5308f943, - 0xf922fef9, - 0xfbd8fed9, - 0x019e7522, - 0x75cfc175, - 0xc375a4c2, - 0x47c4754a, - 0x75a4c575, - 0xc7756dc6, - 0x03d27540, - 0x7510d375, - 0xca7500c9, - 0x00cb75d0, - 0x7500cc75, - 0x9b75009a, - 0x009c75c0, - 0x78009d75, - 0x12827402, - 0xc6438b80, - 0x74097802, - 0x8b8012e7, - 0x75d09075, - 0x9e750291, - 0x01a97502, - 0x00000022, -}; - -extern bool reset_failed; - -irqreturn_t platform_cfg_req_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - const u64 EXYNOS_WLBT = 0x1; - u64 ret64 = 0; - s32 ret = 0; - unsigned int ka_addr = 0x1000; - uint32_t *ka_patch_addr = ka_patch; - u32 id; - -#define CHECK(x) do { \ - int retval = (x); \ - if (retval < 0) \ - goto cfg_error; \ -} while (0) - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "disable_irq\n"); - - /* mask the irq */ - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - /* Was the CFG_REQ irq received from WLBT before we expected it? - * Typically this indicates an issue returning WLBT HW to reset. - */ - if (platform->boot_state != WLBT_BOOT_WAIT_CFG_REQ) { - u32 val; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Spurious CFG_REQ IRQ from WLBT!\n"); - - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_NS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_S 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - reset_failed = true; /* prevent further interaction with HW */ - - return IRQ_HANDLED; - } - - /* CBUS should be ready before we get CFG_REQ, but we suspect - * CBUS is not ready yet. add some delay to see if that helps - */ - udelay(100); - - /* Set TZPC to non-secure mode */ - ret64 = exynos_smc(SMC_CMD_CONN_IF, (EXYNOS_WLBT << 32) | EXYNOS_SET_CONN_TZPC, 0, 0); - if (ret64) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to set TZPC to non-secure mode: %llu\n", ret64); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SMC_CMD_CONN_IF run successfully : %llu\n", ret64); - - /* WLBT_REMAP */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP begin\n"); - CHECK(regmap_write(platform->wlbt_remap, 0x0, WLBT_DBUS_BAAW_0_START >> 12)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP end\n"); - - /* CHIP_VERSION_ID - overload with EMA settings */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "CHIP_VERSION_ID begin\n"); - regmap_read(platform->wlbt_remap, 0x10, &id); - id &= ~CHIP_VERSION_ID_EMA_MASK; - id |= CHIP_VERSION_ID_EMA_VALUE; - CHECK(regmap_write(platform->wlbt_remap, 0x10, id)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "CHIP_VERSION_ID 0x%x end\n", id); - - /* DBUS_BAAW regions */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW begin\n"); - CHECK(regmap_write(platform->dbus_baaw, 0x0, WLBT_DBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x4, WLBT_DBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x8, platform->mem_start >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW end\n"); - - /* PBUS_BAAW regions */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW begin\n"); - CHECK(regmap_write(platform->pbus_baaw, 0x0, WLBT_PBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4, WLBT_PBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x8, WLBT_PBUS_MBOX_CP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x10, WLBT_PBUS_BAAW_1_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x14, WLBT_PBUS_BAAW_1_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x18, WLBT_PBUS_MBOX_SHUB2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x1C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x20, WLBT_PBUS_BAAW_2_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x24, WLBT_PBUS_BAAW_2_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x28, WLBT_PBUS_USI_CMG00_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x2C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x30, WLBT_PBUS_BAAW_3_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x34, WLBT_PBUS_BAAW_3_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x38, WLBT_PBUS_SYSREG_CMGP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x3C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x40, WLBT_PBUS_BAAW_4_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x44, WLBT_PBUS_BAAW_4_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x48, WLBT_PBUS_GPIO_CMGP_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x50, WLBT_PBUS_BAAW_5_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x54, WLBT_PBUS_BAAW_5_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x58, WLBT_PBUS_SHUB_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x5C, WLBT_BAAW_ACCESS_CTRL)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW end\n"); - - /* PMU boot bug workaround */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT begin\n"); - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x1)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT done\n"); - - while (ka_patch_addr < (ka_patch + ARRAY_SIZE(ka_patch))) { - CHECK(regmap_write(platform->boot_cfg, ka_addr, *ka_patch_addr)); - ka_addr += sizeof(ka_patch[0]); - ka_patch_addr++; - } - - /* Notify PMU of configuration done */ - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x0)); - - /* BOOT_CFG_ACK */ - CHECK(regmap_write(platform->boot_cfg, 0x4, 0x1)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_CFG_ACK done\n"); - - /* Delay to allow HW to clear CFG_REQ and hence de-assert IRQ, which - * it does in response to CFG_ACK - */ - udelay(100); - - /* Release ownership of MASK_PWR_REQ */ - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - MASK_PWR_REQ, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to clear WLBT_CTRL_NS[MASK_PWR_REQ]: %d\n", ret); - goto cfg_error; - } - - /* Mark as CFQ_REQ handled, so boot may continue */ - platform->boot_state = WLBT_BOOT_CFG_DONE; - - /* Signal triggering function that the IRQ arrived and CFG was done */ - complete(&platform->cfg_ack); - - /* Re-enable IRQ here to allow spurious interrupt to be tracked */ - enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - return IRQ_HANDLED; -cfg_error: - platform->boot_state = WLBT_BOOT_CFG_ERROR; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ERROR: WLBT Config failed. WLBT will not work\n"); - complete(&platform->cfg_ack); - return IRQ_HANDLED; -} -#endif - -static void platform_mif_unregister_irq(struct platform_mif *platform) -{ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering IRQs\n"); - - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform); - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform); - /* Reset irq_disabled_cnt for WDOG IRQ since the IRQ itself is here unregistered and disabled */ - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* if ALIVE irq is required */ - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform); -#endif -#ifdef CONFIG_SOC_EXYNOS9610 - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform); -#endif -} - -static int platform_mif_register_irq(struct platform_mif *platform) -{ - int err; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering IRQs\n"); - - /* Register MBOX irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering MBOX irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform->wlbt_irq[PLATFORM_MIF_MBOX].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform_mif_isr, - platform->wlbt_irq[PLATFORM_MIF_MBOX].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register MBOX handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - - /* Register WDOG irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering WDOG irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform->wlbt_irq[PLATFORM_MIF_WDOG].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform_wdog_isr, - platform->wlbt_irq[PLATFORM_MIF_WDOG].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register WDOG handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* Register ALIVE irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering ALIVE irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform_alive_isr, - platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags, DRV_NAME, platform); - if (IS_ERR_VALUE(err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register ALIVE handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } -#endif - -#ifdef CONFIG_SOC_EXYNOS9610 - /* Mark as WLBT in reset before enabling IRQ to guard against spurious IRQ */ - platform->boot_state = WLBT_BOOT_IN_RESET; - smp_wmb(); /* commit before irq */ - - /* Register WB2AP_CFG_REQ irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering CFG_REQ irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform_cfg_req_isr, - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register CFG_REQ handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } -#endif - return 0; -} - -static void platform_mif_destroy(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - platform_mif_unregister_irq(platform); -} - -static char *platform_mif_get_uid(struct scsc_mif_abs *interface) -{ - /* Avoid unused parameter error */ - (void)interface; - return "0"; -} - -/* WLBT Power domain */ -static int platform_mif_power(struct scsc_mif_abs *interface, bool power) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val = 0; - s32 ret = 0; -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "power %d\n", power); - - if (power) - val = MASK_PWR_REQ; - - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - MASK_PWR_REQ, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[MASK_PWR_REQ]: %d\n", ret); - return ret; - } -#else - /* See sequence in 8.6.6 */ - /* WIFI power on/off control If WIFI_PWRON = 1 - * and WIFI_START=1, WIFI enters to UP state. - * This bit is 0 as default value because WIFI - * should be reset at AP boot mode after Power-on Reset. - */ - if (power) - val = WIFI_PWRON; - ret = regmap_update_bits(platform->pmureg, WIFI_CTRL_NS, - WIFI_PWRON, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WIFI_CTRL_NS[WIFI_PWRON]: %d\n", ret); - return ret; - } -#endif - return 0; -} - -/* WLBT RESET */ -static int platform_mif_hold_reset(struct scsc_mif_abs *interface, bool reset) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val = 0; - s32 ret = 0; -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "reset %d\n", reset); - if (reset) - val = WLBT_RESET_SET; - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_RESET_SET, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[WLBT_RESET_SET]: %d\n", ret); - return ret; - } -#else - if (reset) - val = WIFI_RESET_SET; - /* See sequence in 8.6.6 */ - ret = regmap_update_bits(platform->pmureg, WIFI_CTRL_NS, - WIFI_RESET_SET, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WIFI_CTRL_NS[WIFI_RESET_SET]: %d\n", ret); - return ret; - } -#endif - return 0; -} - -/* WLBT START */ -static int platform_mif_start(struct scsc_mif_abs *interface, bool start) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val = 0; - s32 ret = 0; - -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "start %d\n", start); - if (start) - val = WLBT_START; - - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S, - WLBT_START, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret); - return ret; - } - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "update WIFI_CTRL_S[WIFI_START]: %d\n", ret); - - /* At this point WLBT should assert the CFG_REQ IRQ, so wait for it */ - if (start && - wait_for_completion_timeout(&platform->cfg_ack, WLBT_BOOT_TIMEOUT) == 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Timeout waiting for CFG_REQ IRQ\n"); - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - return -ETIMEDOUT; - } - /* only continue if CFG_REQ IRQ configured WLBT/PMU correctly */ - if (platform->boot_state == WLBT_BOOT_CFG_ERROR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "CFG_REQ failed to configure WLBT.\n"); - return -EIO; - } -#else - if (start) - val = WIFI_START; - /* See sequence in 8.6.6 */ - ret = regmap_update_bits(platform->pmureg, WIFI_CTRL_S, - WIFI_START, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WIFI_CTRL_S[WIFI_START]: %d\n", ret); - return ret; - } -#endif - return 0; -} - -static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface) -{ - int ret = 0; - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - -#ifdef CONFIG_SOC_EXYNOS9610 - /* We're now ready for the IRQ */ - platform->boot_state = WLBT_BOOT_WAIT_CFG_REQ; - smp_wmb(); /* commit before irq */ -#endif - ret = platform_mif_power(interface, true); - if (ret) - return ret; - ret = platform_mif_hold_reset(interface, false); - if (ret) - return ret; - ret = platform_mif_start(interface, true); - if (ret) - return ret; - - return ret; -} - -int __platform_mif_9610_recover_reset(struct platform_mif *platform) -{ - unsigned long timeout; - int ret; - u32 val; - - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Attempt to recover WLBT HW reset"); - - /* - * Set CFG_ACK = 1 - * Poll CFG_REQ until REQ == 0 - * Set CFG_ACK = 0 - * Poll CENTRAL_SEQ_WLBT_STATUS SM status again - * Print WLBT_DEBUG at each step. - * (Remember to set "echo 1 > /sys/kernel/debug/exynos-rgt/vqmmc/enable" before the test). - */ - - /* CFG_ACK = 1 */ - regmap_write(platform->boot_cfg, 0x4, 0x1); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Force BOOT_CFG_ACK = 1\n"); - - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - /* TBD poll CFG_REQ status */ - udelay(250); - - /* CFG_ACK = 0 */ - regmap_write(platform->boot_cfg, 0x4, 0x0); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Force BOOT_CFG_ACK = 0\n"); - - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - /* Check WLBT_STATUS again */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - val &= STATES; - val >>= 16; - if (val == 0x80) { - ret = 0; /* Recovered OK */ - goto done; - } - } while (time_before(jiffies, timeout)); - ret = -ETIME; - -done: - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - if (ret == 0) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Recovered reset"); - else - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Reset not recovered"); - - /* Save log at point of failure, last to show recovery attempt */ -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_schedule_collection(SCSC_LOG_HOST_COMMON, SCSC_LOG_HOST_COMMON_RECOVER_RST); -#else - mx140_log_dump(); -#endif - return ret; -} - -static int platform_mif_pmu_reset(struct scsc_mif_abs *interface, u8 rst_case) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long timeout; - int ret; - u32 val; - - if (rst_case == 0 || rst_case > 2) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Incorrect pmu reset case %d\n", rst_case); - return -EIO; - } - -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - ret = regmap_update_bits(platform->pmureg, RESET_AHEAD_WIFI_PWR_REG, - SYS_PWR_CFG_2, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update RESET_ASB_WIFI_SYS_PWR_REG %d\n", ret); - return ret; - } -#elif defined(CONFIG_SOC_EXYNOS7570) - ret = regmap_update_bits(platform->pmureg, RESET_ASB_WIFI_SYS_PWR_REG, - SYS_PWR_CFG_2, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update RESET_ASB_WIFI_SYS_PWR_REG %d\n", ret); - return ret; - } - -#endif -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "rst_case %d\n", rst_case); - - /* Revert power control ownership to AP, as WLBT is going down (S9.6.6). */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - MASK_PWR_REQ, MASK_PWR_REQ); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[MASK_PWR_REQ]: %d\n", ret); - return ret; - } - - /* reset sequence as per excite implementation for Leman */ - ret = regmap_update_bits(platform->pmureg, CENTRAL_SEQ_WLBT_CONFIGURATION, - SYS_PWR_CFG_16, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update CENTRAL_SEQ_WLBT_CONFIGURATION %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, RESET_AHEAD_WLBT_SYS_PWR_REG, - SYS_PWR_CFG_2, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update RESET_AHEAD_WLBT_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, CLEANY_BUS_WLBT_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update CLEANY_BUS_WLBT_SYS_PWR_REG%d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, LOGIC_RESET_WLBT_SYS_PWR_REG, - SYS_PWR_CFG_2, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update LOGIC_RESET_WLBT_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, TCXO_GATE_WLBT_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update TCXO_GATE_WLBT_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, WLBT_DISABLE_ISO_SYS_PWR_REG, - SYS_PWR_CFG, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_DISABLE_ISO_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, WLBT_RESET_ISO_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_RESET_ISO_SYS_PWR_REG %d\n", ret); - return ret; - } - - /* rst_case is always 2 on 9610 */ - ret = platform_mif_hold_reset(interface, true); - - if (ret) - return ret; - - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - val &= STATES; - val >>= 16; - if (val == 0x80) { - /* OK. Switch CTRL_NS[MASK_PWR_REQ] ownership to FW following - * reset. WLBT PWR_REQ is cleared when it's put in reset. - * The SW PWR_REQ remains asserted, but as ownership is now FW, - * it'll be ignored. This leaves it as we found it. - */ - platform_mif_power(interface, false); - - return 0; /* OK - return */ - } - } while (time_before(jiffies, timeout)); - - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Timeout waiting for CENTRAL_SEQ_WLBT_STATUS SM status\n"); - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - -#if 0 - /* Try to recovery in case of reset failure */ - ret = __platform_mif_9610_recover_reset(platform); - if (!ret) - return 0; -#endif -#else - /* 7885, 7872, 7570 */ - ret = regmap_update_bits(platform->pmureg, CLEANY_BUS_WIFI_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update CLEANY_BUS_WIFI_SYS_PWR_REG%d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, LOGIC_RESET_WIFI_SYS_PWR_REG, - SYS_PWR_CFG_2, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update LOGIC_RESET_WIFI_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, TCXO_GATE_WIFI_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update TCXO_GATE_WIFI_SYS_PWR_REG %d\n", ret); - return ret; - } -#endif -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - ret = regmap_update_bits(platform->pmureg, WIFI_DISABLE_ISO_SYS_PWR_REG, - SYS_PWR_CFG, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WIFI_DISABLE_ISO_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, WIFI_RESET_ISO_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WIFI_RESET_ISO_SYS_PWR_REG %d\n", ret); - return ret; - } -#endif -#ifdef CONFIG_SOC_EXYNOS9610 - (void)platform; - (void)timeout; - (void)ret; - (void)val; -#else - /* 7885, 7872, 7570 */ - ret = regmap_update_bits(platform->pmureg, CENTRAL_SEQ_WIFI_CONFIGURATION, - SYS_PWR_CFG_16, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update CENTRAL_SEQ_WIFI_CONFIGURATION %d\n", ret); - return ret; - } - - if (rst_case == 1) - ret = platform_mif_power(interface, false); - else - ret = platform_mif_hold_reset(interface, true); - - if (ret) - return ret; - - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, CENTRAL_SEQ_WIFI_STATUS, &val); - val &= STATES; - val >>= 16; - if (val == 0x80) - return 0; - } while (time_before(jiffies, timeout)); - - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Timeout waiting for CENTRAL_SEQ_WIFI_STATUS SM status\n"); -#endif - return -ETIME; -} - -/* reset=0 - release from reset */ -/* reset=1 - hold reset */ -static int platform_mif_reset(struct scsc_mif_abs *interface, bool reset) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 ret = 0; - u32 val; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (enable_platform_mif_arm_reset || !reset) { - if (!reset) { /* Release from reset */ -#ifdef CONFIG_ARCH_EXYNOS - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SOC_VERSION: product_id 0x%x, rev 0x%x\n", - exynos_soc_info.product_id, exynos_soc_info.revision); -#endif -#ifdef CONFIG_SOC_EXYNOS9610 - (void)val; -#else - /* Enable R4 access to MIF resources */ - /* Address is fixed and its value is in the dts */ - /* It defines the base address of DRAM space which WIFI accesses. - * Default value is 0x0_6000_0000. It can configure only MSB 14-bit. - * You must align this base address with WIFI memory access size that WIFI_MEM_SIZE - * defines - */ - /* >>12 represents 4K aligment (see size)*/ - val = (platform->mem_start & 0xFFFFFC000) >> 12; - regmap_write(platform->pmureg, WIFI2AP_MEM_CONFIG1, val); - /* Size */ - /*It defines the DRAM memory size to which WLBT can - * access. - * Definition of the size has 4 KB resolution defined from - * minimum 4 KB to maximum 1GB. - * 20'b0000_0000_0000_0000_0001 = 4KB - * 20'b0000_0000_0000_0000_0010 = 8KB - * 20'b0000_0000_0001_0000_0000 = 1 MB - * 20'b0000_0000_0010_0000_0000 = 2 MB - * 20'b0000_0000_0100_0000_0000 = 4 MB (default) - * 20'b0000_0000_1000_0000_0000 = 8 MB - * 20'b0000_1000_0000_0000_0000 = 128 MB - * 20'b0100_0000_0000_0000_0000 = 1 GB - */ - /* Size is fixed and its value is in the dts */ - /* >>12 represents 4K aligment (see address)*/ - val = platform->mem_size >> 12; - regmap_write(platform->pmureg, WIFI2AP_MEM_CONFIG0, val); -#endif -#if (defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885)) && defined(CONFIG_ACPM_DVFS) - /* Immediately prior to reset release, set up ACPM - * to ensure BUCK2 gets the right voltage - */ - exynos_acpm_set_flag(); -#endif - ret = platform_mif_pmu_reset_release(interface); - } else { - /* Put back into reset */ - ret = platform_mif_pmu_reset(interface, 2); -#if !defined(CONFIG_SOC_EXYNOS9610) - /* WLBT should be stopped/powered-down at this point */ - regmap_write(platform->pmureg, WIFI2AP_MEM_CONFIG1, 0x00000); - regmap_write(platform->pmureg, WIFI2AP_MEM_CONFIG0, 0x00000); -#endif - } - } else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Not resetting ARM Cores - enable_platform_mif_arm_reset: %d\n", - enable_platform_mif_arm_reset); - return ret; -} - -static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size) -{ - int i; - struct page **pages; - void *vmem; - - size = PAGE_ALIGN(size); - - pages = kmalloc((size >> PAGE_SHIFT) * sizeof(*pages), GFP_KERNEL); - if (!pages) - return NULL; - - /* Map NORMAL_NC pages with kernel virtual space */ - for (i = 0; i < (size >> PAGE_SHIFT); i++) { - pages[i] = phys_to_page(phys_addr); - phys_addr += PAGE_SIZE; - } - - vmem = vmap(pages, size >> PAGE_SHIFT, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); - - kfree(pages); - return (void __iomem *)vmem; -} - -static void platform_mif_unmap_region(void *vmem) -{ - vunmap(vmem); -} - -static void *platform_mif_map(struct scsc_mif_abs *interface, size_t *allocated) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - if (allocated) - *allocated = 0; - - platform->mem = - platform_mif_map_region(platform->mem_start, platform->mem_size); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Error remaping shared memory\n"); - return NULL; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Map: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - - /* Initialise MIF registers with documented defaults */ - /* MBOXes */ - for (i = 0; i < NUM_MBOX_PLAT; i++) { - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(ISSR(i)), 0x00000000); -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - platform_mif_reg_write_m4(platform, MAILBOX_WLBT_REG(ISSR(i)), 0x00000000); -#endif - } - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); -#ifdef CONFIG_SOC_EXYNOS7570 - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR2), 0x0000ffff); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - platform_mif_reg_write_m4(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); -#endif - - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); -#ifdef CONFIG_SOC_EXYNOS7570 - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR2), 0x0000ffff); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - platform_mif_reg_write_m4(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); -#endif -#if !defined(CONFIG_SOC_EXYNOS9610) - /*Set WLBT_BOOT_TEST_RST_CFG to 0 to boot from external DRAM */ - regmap_write(platform->pmureg, WLBT_BOOT_TEST_RST_CFG, 0x00000); -#endif - /* Add more requrired initialization here: */ - -#ifdef CONFIG_SCSC_GPR4_CON_DEBUG - /* PIO muxes switching to the Maxwell subsystem */ - /* GPR4_CON (0x13750040) = 0x00666666 */ - if (gpr4_debug) { - reg_bkp = readl(gpio_base); - writel(0x00666666, gpio_base); - SCSC_TAG_WARNING_DEV(PLAT_MIF, platform->dev, "[WARNING] Changing GPR4_CON from 0x%x to 0x%x", reg_bkp, readl(gpio_base)); - reg_update = true; - } -#endif - -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_disable_irq == true) { - if (allocated) - *allocated = platform->mem_size; - return platform->mem; - } -#endif - /* register interrupts */ - if (platform_mif_register_irq(platform)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - return NULL; - } - - if (allocated) - *allocated = platform->mem_size; - /* Set the CR4 base address in Mailbox??*/ - return platform->mem; -} - -/* HERE: Not sure why mem is passed in - its stored in platform - as it should be */ -static void platform_mif_unmap(struct scsc_mif_abs *interface, void *mem) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - -#ifdef CONFIG_SCSC_GPR4_CON_DEBUG - u32 prev; - - if (gpr4_debug && reg_update) { - prev = readl(gpio_base); - writel(reg_bkp, gpio_base); - SCSC_TAG_WARNING_DEV(PLAT_MIF, platform->dev, "[WARNING] Restoring GPR4_CON from 0x%x to 0x%x", prev, readl(gpio_base)); - } - reg_update = false; -#endif - /* Avoid unused parameter error */ - (void)mem; - - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); -#ifdef CONFIG_SOC_EXYNOS7570 - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR2), 0x0000ffff); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - platform_mif_reg_write_m4(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); -#endif - -#ifdef CONFIG_SCSC_CHV_SUPPORT - /* Restore PIO changed by Maxwell subsystem */ - if (chv_disable_irq == false) - /* Unregister IRQs */ - platform_mif_unregister_irq(platform); -#else - platform_mif_unregister_irq(platform); -#endif - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); -#ifdef CONFIG_SOC_EXYNOS7570 - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR2), 0x0000ffff); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - platform_mif_reg_write_m4(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - platform->mem = NULL; -} - -static u32 platform_mif_irq_bit_mask_status_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INTMR0: 0x%x\n", val); - return val; -} - -static u32 platform_mif_irq_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - /* Function has to return the interrupts that are enabled *AND* not masked */ - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INT-INTMSR0: 0x%x\n", val); - - return val; -} - -static void platform_mif_irq_bit_set(struct scsc_mif_abs *interface, int bit_num, enum scsc_mif_abs_target target) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 reg; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } -#ifdef CONFIG_SOC_EXYNOS9610 - reg = INTGR1; - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(reg), (1 << bit_num)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTGR1: bit %d on target %d\n", bit_num, target); -#else - /* Generate INT to R4/M4 - VIC */ - if (target == SCSC_MIF_ABS_TARGET_R4) - reg = INTGR1; - else if (target == SCSC_MIF_ABS_TARGET_M4) -#ifdef CONFIG_SOC_EXYNOS7570 - reg = INTGR2; -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - reg = INTGR1; -#endif - else { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect Target %d\n", target); - return; - } -#endif -#ifdef CONFIG_SOC_EXYNOS7570 - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(reg), (1 << bit_num)); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - if (target == SCSC_MIF_ABS_TARGET_R4) - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(reg), (1 << bit_num)); - else - platform_mif_reg_write_m4(platform, MAILBOX_WLBT_REG(reg), (1 << bit_num)); -#endif - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTGR1: bit %d on target %d\n", bit_num, target); -} - -static void platform_mif_irq_bit_clear(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - /* WRITE : 1 = Clears Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), ((1 << bit_num) << 16)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTCR0: bit %d\n", bit_num); -} - -static void platform_mif_irq_bit_mask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 1 = Mask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val | ((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTMR0: 0x%x bit %d\n", val | (1 << bit_num), bit_num); -} - -static void platform_mif_irq_bit_unmask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 0 = Unmask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val & ~((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "UNMASK Setting INTMR0: 0x%x bit %d\n", val & ~((1 << bit_num) << 16), bit_num); -} - -/* Return the contents of the mask register */ -static u32 __platform_mif_irq_bit_mask_read(struct platform_mif *platform) -{ - u32 val; - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Read INTMR0: 0x%x\n", val); - - return val; -} - -/* Write the mask register, destroying previous contents */ -static void __platform_mif_irq_bit_mask_write(struct platform_mif *platform, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Write INTMR0: 0x%x\n", val); -} - -static void platform_mif_irq_reg_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif int handler %pS in %p %p\n", handler, platform, interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = handler; - platform->irq_dev = dev; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif int handler %pS\n", interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_reg_reset_request_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif reset_request int handler %pS in %p %p\n", handler, platform, interface); - platform->reset_request_handler = handler; - platform->irq_reset_request_dev = dev; - if (atomic_read(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "Default WDOG handler disabled by spurios IRQ...re-enabling.\n"); - enable_irq(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); - } -} - -static void platform_mif_irq_unreg_reset_request_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "UnRegistering mif reset_request int handler %pS\n", interface); - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; -} - -static void platform_mif_suspend_reg_handler(struct scsc_mif_abs *interface, - int (*suspend)(struct scsc_mif_abs *abs, void *data), - void (*resume)(struct scsc_mif_abs *abs, void *data), - void *data) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = suspend; - platform->resume_handler = resume; - platform->suspendresume_data = data; -} - -static void platform_mif_suspend_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; -} - -static u32 *platform_mif_get_mbox_ptr(struct scsc_mif_abs *interface, u32 mbox_index) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 *addr; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "mbox_index 0x%x\n", mbox_index); - addr = platform->base + MAILBOX_WLBT_REG(ISSR(mbox_index)); - return addr; -} - -static int platform_mif_get_mifram_ref(struct scsc_mif_abs *interface, void *ptr, scsc_mifram_ref *ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return -ENOMEM; - } - - /* Check limits! */ - if (ptr >= (platform->mem + platform->mem_size)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Unable to get pointer reference\n"); - return -ENOMEM; - } - - *ref = (scsc_mifram_ref)((uintptr_t)ptr - (uintptr_t)platform->mem); - - return 0; -} - -static void *platform_mif_get_mifram_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - /* Check limits */ - if (ref >= 0 && ref < platform->mem_size) - return (void *)((uintptr_t)platform->mem + (uintptr_t)ref); - else - return NULL; -} - -static void *platform_mif_get_mifram_phy_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem_start) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - return (void *)((uintptr_t)platform->mem_start + (uintptr_t)ref); -} - -static uintptr_t platform_mif_get_mif_pfn(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - return vmalloc_to_pfn(platform->mem); -} - -static struct device *platform_mif_get_mif_device(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - return platform->dev; -} - -static void platform_mif_irq_clear(void) -{ - /* Implement if required */ -} - -static int platform_mif_read_register(struct scsc_mif_abs *interface, u64 id, u32 *val) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (id == SCSC_REG_READ_WLBT_STAT) { - regmap_read(platform->pmureg, WLBT_STAT, val); - return 0; - } - - return -EIO; -} - -static void platform_mif_dump_register(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR1))); -#ifdef CONFIG_SOC_EXYNOS7570 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR2 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR2))); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR1(M4) 0x%08x\n", platform_mif_reg_read_m4(platform, MAILBOX_WLBT_REG(INTGR1))); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR1))); -#ifdef CONFIG_SOC_EXYNOS7570 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR2 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR2))); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR1(M4) 0x%08x\n", platform_mif_reg_read_m4(platform, MAILBOX_WLBT_REG(INTCR1))); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR1))); -#ifdef CONFIG_SOC_EXYNOS7570 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR2 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR2))); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR1(M4) 0x%08x\n", platform_mif_reg_read_m4(platform, MAILBOX_WLBT_REG(INTMR1))); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR1))); -#ifdef CONFIG_SOC_EXYNOS7570 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR2 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR2))); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR1(M4) 0x%08x\n", platform_mif_reg_read_m4(platform, MAILBOX_WLBT_REG(INTSR1))); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR1))); -#ifdef CONFIG_SOC_EXYNOS7570 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR2 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR2))); -#elif defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR1(M4) 0x%08x\n", platform_mif_reg_read_m4(platform, MAILBOX_WLBT_REG(INTMSR1))); -#endif - - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_cleanup(struct scsc_mif_abs *interface) -{ -#ifdef CONFIG_SCSC_CLK20MHZ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - /* Restore USBPLL owenership to the AP so that USB driver may control it */ - __platform_mif_usbpll_claim(platform, false); -#endif -} - -static void platform_mif_restart(struct scsc_mif_abs *interface) -{ -#ifdef CONFIG_SCSC_CLK20MHZ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - /* Restore USBPLL owenership to the wlbt */ - __platform_mif_usbpll_claim(platform, true); -#endif -} - -#ifdef CONFIG_OF_RESERVED_MEM -static int __init platform_mif_wifibt_if_reserved_mem_setup(struct reserved_mem *remem) -{ - SCSC_TAG_DEBUG(PLAT_MIF, "memory reserved: mem_base=%#lx, mem_size=%zd\n", - (unsigned long)remem->base, (size_t)remem->size); - - sharedmem_base = remem->base; - sharedmem_size = remem->size; - return 0; -} -RESERVEDMEM_OF_DECLARE(wifibt_if, "exynos,wifibt_if", platform_mif_wifibt_if_reserved_mem_setup); -#endif - -#ifdef CONFIG_SCSC_CLK20MHZ -static void __platform_mif_usbpll_claim(struct platform_mif *platform, bool wlbt) -{ - - s32 ret = 0; - - if (!platform->cmu_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "USBPLL claim not enabled\n"); - return; - } - - /* Set USBPLL ownership, by setting AP2WLBT_USBPLL_WPLL_SEL */ - - if (wlbt) { - /* WLBT f/w has control */ - ret = regmap_update_bits(platform->cmu_base, USBPLL_CON1, AP2WLBT_USBPLL_WPLL_SEL, 0); - if (ret < 0) - goto error; - } else { - /* Ensure PLL runs */ - ret = regmap_update_bits(platform->cmu_base, USBPLL_CON1, AP2WLBT_USBPLL_WPLL_EN, AP2WLBT_USBPLL_WPLL_EN); - if (ret < 0) - goto error; - - /* AP has control */ - udelay(platform->usbpll_delay); - ret = regmap_update_bits(platform->cmu_base, USBPLL_CON1, AP2WLBT_USBPLL_WPLL_SEL, AP2WLBT_USBPLL_WPLL_SEL); - if (ret < 0) - goto error; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "USBPLL_CON1 assigned to %s\n", wlbt ? "WLBT" : "AP"); - return; - -error: - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Failed to update USBPLL_CON1 to %s\n", wlbt ? "WLBT" : "AP"); - -} -#endif - -struct scsc_mif_abs *platform_mif_create(struct platform_device *pdev) -{ - struct scsc_mif_abs *platform_if; - struct platform_mif *platform = - (struct platform_mif *)devm_kzalloc(&pdev->dev, sizeof(struct platform_mif), GFP_KERNEL); - int err = 0; - u8 i = 0; - struct resource *reg_res; -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - struct resource *reg_res_m4; -#endif -#ifdef CONFIG_SCSC_CLK20MHZ - /* usb pll ownership */ - const char *usbowner = NULL; - u32 usbdelay = 0; -#endif -#ifdef CONFIG_SCSC_SMAPPER - u32 smapper_banks = 0; -#endif - - if (!platform) - return NULL; - - SCSC_TAG_INFO_DEV(PLAT_MIF, &pdev->dev, "Creating MIF platform device\n"); - - platform_if = &platform->interface; - - /* initialise interface structure */ - platform_if->destroy = platform_mif_destroy; - platform_if->get_uid = platform_mif_get_uid; - platform_if->reset = platform_mif_reset; - platform_if->map = platform_mif_map; - platform_if->unmap = platform_mif_unmap; - platform_if->irq_bit_set = platform_mif_irq_bit_set; - platform_if->irq_get = platform_mif_irq_get; - platform_if->irq_bit_mask_status_get = platform_mif_irq_bit_mask_status_get; - platform_if->irq_bit_clear = platform_mif_irq_bit_clear; - platform_if->irq_bit_mask = platform_mif_irq_bit_mask; - platform_if->irq_bit_unmask = platform_mif_irq_bit_unmask; - platform_if->irq_reg_handler = platform_mif_irq_reg_handler; - platform_if->irq_unreg_handler = platform_mif_irq_unreg_handler; - platform_if->irq_reg_reset_request_handler = platform_mif_irq_reg_reset_request_handler; - platform_if->irq_unreg_reset_request_handler = platform_mif_irq_unreg_reset_request_handler; - platform_if->suspend_reg_handler = platform_mif_suspend_reg_handler; - platform_if->suspend_unreg_handler = platform_mif_suspend_unreg_handler; - platform_if->get_mbox_ptr = platform_mif_get_mbox_ptr; - platform_if->get_mifram_ptr = platform_mif_get_mifram_ptr; - platform_if->get_mifram_ref = platform_mif_get_mifram_ref; - platform_if->get_mifram_pfn = platform_mif_get_mif_pfn; - platform_if->get_mifram_phy_ptr = platform_mif_get_mifram_phy_ptr; - platform_if->get_mif_device = platform_mif_get_mif_device; - platform_if->irq_clear = platform_mif_irq_clear; - platform_if->mif_dump_registers = platform_mif_dump_register; - platform_if->mif_read_register = platform_mif_read_register; - platform_if->mif_cleanup = platform_mif_cleanup; - platform_if->mif_restart = platform_mif_restart; -#ifdef CONFIG_SCSC_SMAPPER - platform_if->mif_smapper_get_mapping = platform_mif_smapper_get_mapping; - platform_if->mif_smapper_get_bank_info = platform_mif_smapper_get_bank_info; - platform_if->mif_smapper_write_sram = platform_mif_smapper_write_sram; - platform_if->mif_smapper_configure = platform_mif_smapper_configure; - platform_if->mif_smapper_get_bank_base_address = platform_mif_smapper_get_bank_base_address; -#endif -#ifdef CONFIG_SCSC_QOS - platform_if->mif_pm_qos_add_request = platform_mif_pm_qos_add_request; - platform_if->mif_pm_qos_update_request = platform_mif_pm_qos_update_request; - platform_if->mif_pm_qos_remove_request = platform_mif_pm_qos_remove_request; -#endif - /* Update state */ - platform->pdev = pdev; - platform->dev = &pdev->dev; - - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; - -#ifdef CONFIG_OF_RESERVED_MEM - platform->mem_start = sharedmem_base; - platform->mem_size = sharedmem_size; -#else - /* If CONFIG_OF_RESERVED_MEM is not defined, sharedmem values should be - * parsed from the scsc_wifibt binding - */ - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-base", &sharedmem_base)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_start = sharedmem_base; - - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-size", &sharedmem_size)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_size = sharedmem_size; -#endif -#ifdef CONFIG_SCSC_SMAPPER - platform->smapper = NULL; -#endif -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - /* TZASC configuration is required for WLBT to access DRAM from Katmai onward */ - /* Base address should be 4KB aligned. This call needs proper support in EL3_MON */ - err = exynos_smc(EXYNOS_SMC_WLBT_TZASC_CMD, WLBT_TZASC, platform->mem_start, - platform->mem_size); - /* Anyway we keep on WLBT initialization even if TZASC failed to minimize disruption*/ - if (err) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "WLBT Failed to configure TZASC, err=%d. DRAM could be NOT accessible in secure mode\n", err); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT TZASC configured OK\n"); -#endif - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->mem_start 0x%x platform->mem_size 0x%x\n", (u32)platform->mem_start, (u32)platform->mem_size); - if (platform->mem_start == 0) - SCSC_TAG_WARNING_DEV(PLAT_MIF, platform->dev, "platform->mem_start is 0"); - - if (platform->mem_size == 0) { - /* We return return if mem_size is 0 as it does not make any sense. - * This may be an indication of an incorrect platform device binding. - */ - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "platform->mem_size is 0"); - err = -EINVAL; - goto error_exit; - } - - /* Memory resource - Phys Address of MAILBOX_WLBT register map */ - reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!reg_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error getting mem resource for MAILBOX_WLBT\n"); - err = -ENOENT; - goto error_exit; - } - - platform->reg_start = reg_res->start; - platform->reg_size = resource_size(reg_res); - - platform->base = - devm_ioremap_nocache(platform->dev, reg_res->start, resource_size(reg_res)); - - if (!platform->base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping register region\n"); - err = -EBUSY; - goto error_exit; - } - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->reg_start %lx size %x base %p\n", (uintptr_t)platform->reg_start, (u32)platform->reg_size, platform->base); - -#if defined(CONFIG_SOC_EXYNOS7872) || defined(CONFIG_SOC_EXYNOS7885) - /* Memory resource for M4 MBOX bank - Phys Address of MAILBOX_WLBT register map */ - reg_res_m4 = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!reg_res_m4) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Error getting mem resource for MAILBOX_WLBT\n"); - err = -ENOENT; - goto error_exit; - } - platform->reg_start_m4 = reg_res_m4->start; - platform->reg_size_m4 = resource_size(reg_res_m4); - - platform->base_m4 = - devm_ioremap_nocache(platform->dev, reg_res_m4->start, resource_size(reg_res_m4)); - - if (!platform->base_m4) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping M4 register region\n"); - err = -EBUSY; - goto error_exit; - } - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->reg_start_m4 %lx size_m4 %x base_m4 %p\n", (uintptr_t)platform->reg_start_m4, (u32)platform->reg_size_m4, platform->base_m4); -#endif - -#ifdef CONFIG_SCSC_CLK20MHZ - /* Get usbpll,owner if Maxwell has to provide 20Mhz clock to USB subsystem */ - platform->cmu_base = NULL; - if (of_property_read_string(pdev->dev.of_node, "usbpll,owner", &usbowner)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "usbpll,owner of_property does not exist or is invalid\n"); - goto cont; - } else { - if (strcasecmp(usbowner, "y")) - goto skip_usbpll; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "usbpll,owner is enabled\n"); - - /* CMU_FSYS reg map - syscon */ - platform->cmu_base = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,syscon-cmu_fsys"); - if (IS_ERR(platform->cmu_base)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "syscon regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->cmu_base)); - goto skip_usbpll; - } - - if (of_property_read_u32(pdev->dev.of_node, "usbpll,udelay", &usbdelay)) - goto skip_usbpll; - platform->usbpll_delay = usbdelay; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Mapping CMU_FSYS with %dus delay\n", usbdelay); - - goto cont; -skip_usbpll: - platform->cmu_base = NULL; - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "usbpll owner skipped\n"); - } -cont: -#endif -#ifdef CONFIG_SCSC_GPR4_CON_DEBUG - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Mapping GPR4_CON 0x13750040\n"); - gpio_base = - devm_ioremap_nocache(platform->dev, 0x13750040, 4); -#endif - - /* Get the 4 IRQ resources */ - for (i = 0; i < 4; i++) { - struct resource *irq_res; - int irqtag; - - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!irq_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "No IRQ resource at index %d\n", i); - err = -ENOENT; - goto error_exit; - } - - if (!strcmp(irq_res->name, "MBOX")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MBOX irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_MBOX; - } else if (!strcmp(irq_res->name, "ALIVE")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "ALIVE irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_ALIVE; - } else if (!strcmp(irq_res->name, "WDOG")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_WDOG; - } else if (!strcmp(irq_res->name, "CFG_REQ")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "CFG_REQ irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_CFG_REQ; - } else { - SCSC_TAG_ERR_DEV(PLAT_MIF, &pdev->dev, "Invalid irq res name: %s\n", - irq_res->name); - err = -EINVAL; - goto error_exit; - } - platform->wlbt_irq[irqtag].irq_num = irq_res->start; - platform->wlbt_irq[irqtag].flags = (irq_res->flags & IRQF_TRIGGER_MASK); - atomic_set(&platform->wlbt_irq[irqtag].irq_disabled_cnt, 0); - } - - /* PMU reg map - syscon */ - platform->pmureg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,syscon-phandle"); - if (IS_ERR(platform->pmureg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "syscon regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->pmureg)); - err = -EINVAL; - goto error_exit; - } - -#ifdef CONFIG_SOC_EXYNOS9610 - /* Completion event and state used to indicate CFG_REQ IRQ occurred */ - init_completion(&platform->cfg_ack); - platform->boot_state = WLBT_BOOT_IN_RESET; - - /* BAAW_P_WLBT */ - platform->baaw_p_wlbt = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,baaw_p_wlbt-syscon-phandle"); - if (IS_ERR(platform->baaw_p_wlbt)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "baaw_p_wlbt regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->baaw_p_wlbt)); - err = -EINVAL; - goto error_exit; - } - - /* DBUS_BAAW */ - platform->dbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,dbus_baaw-syscon-phandle"); - if (IS_ERR(platform->dbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "dbus_baaw regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->dbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* PBUS_BAAW */ - platform->pbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,pbus_baaw-syscon-phandle"); - if (IS_ERR(platform->pbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "pbus_baaw regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->pbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* WLBT_REMAP */ - platform->wlbt_remap = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,wlbt_remap-syscon-phandle"); - if (IS_ERR(platform->wlbt_remap)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "wlbt_remap regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->wlbt_remap)); - err = -EINVAL; - goto error_exit; - } - - /* BOOT_CFG */ - platform->boot_cfg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,boot_cfg-syscon-phandle"); - if (IS_ERR(platform->boot_cfg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "boot_cfg regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->boot_cfg)); - err = -EINVAL; - goto error_exit; - } -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER parsing */ - if (!of_property_read_u32(pdev->dev.of_node, "smapper_num_banks", &smapper_banks)) - platform_mif_parse_smapper(platform, platform->dev->of_node, smapper_banks); - -#endif -#ifdef CONFIG_SCSC_QOS - platform_mif_parse_qos(platform, platform->dev->of_node); -#endif -#ifdef CONFIG_SCSC_CLK20MHZ - /* Assign USBPLL ownership to WLBT f/w */ - __platform_mif_usbpll_claim(platform, true); -#endif - - /* Initialize spinlock */ - spin_lock_init(&platform->mif_spinlock); - -#ifndef CONFIG_SOC_EXYNOS9610 - /* Clear WIFI_ACTIVE flag in WAKEUP_STAT */ - err = regmap_update_bits(platform->pmureg, WIFI_CTRL_NS, WIFI_ACTIVE_CLR, 1); - if (err < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WIFI_CTRL_NS[WIFI_ACTIVE_CLR]: %d\n", err); - } -#endif - return platform_if; - -error_exit: - devm_kfree(&pdev->dev, platform); - return NULL; -} - -void platform_mif_destroy_platform(struct platform_device *pdev, struct scsc_mif_abs *interface) -{ -#ifdef CONFIG_SCSC_CLK20MHZ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - /* Assign USBPLL ownership to AP */ - __platform_mif_usbpll_claim(platform, false); -#endif -} - -struct platform_device *platform_mif_get_platform_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->pdev; -} - -struct device *platform_mif_get_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->dev; -} - -/* Preserve MIF registers during suspend. - * If all users of the MIF (AP, mx140, CP, etc) release it, the registers - * will lose their values. Save the useful subset here. - * - * Assumption: the AP will not change the register values between the suspend - * and resume handlers being called! - */ -static void platform_mif_reg_save(struct platform_mif *platform) -{ - platform->mif_preserve.irq_bit_mask = __platform_mif_irq_bit_mask_read(platform); -} - -/* Restore MIF registers that may have been lost during suspend */ -static void platform_mif_reg_restore(struct platform_mif *platform) -{ - __platform_mif_irq_bit_mask_write(platform, platform->mif_preserve.irq_bit_mask); -} - -int platform_mif_suspend(struct scsc_mif_abs *interface) -{ - int r = 0; - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (platform->suspend_handler) - r = platform->suspend_handler(interface, platform->suspendresume_data); - - /* Save the MIF registers. - * This must be done last as the suspend_handler may use the MIF - */ - platform_mif_reg_save(platform); - - return r; -} - -void platform_mif_resume(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - s32 ret; - - /* Restore the MIF registers. - * This must be done first as the resume_handler may use the MIF. - */ - platform_mif_reg_restore(platform); -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clear WLBT_ACTIVE_CLR flag\n"); - /* Clear WLBT_ACTIVE_CLR flag in WLBT_CTRL_NS */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, WLBT_ACTIVE_CLR, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret); - } -#else - /* Clear WIFI_ACTIVE flag in WAKEUP_STAT */ - ret = regmap_update_bits(platform->pmureg, WIFI_CTRL_NS, WIFI_ACTIVE_CLR, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WIFI_CTRL_NS[WIFI_ACTIVE_CLR]: %d\n", ret); - } -#endif - if (platform->resume_handler) - platform->resume_handler(interface, platform->suspendresume_data); -} diff --git a/drivers/misc/samsung/scsc/platform_mif.h b/drivers/misc/samsung/scsc/platform_mif.h deleted file mode 100644 index 7db2867a1881..000000000000 --- a/drivers/misc/samsung/scsc/platform_mif.h +++ /dev/null @@ -1,31 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __PLATFORM_MIF_H -#define __PLATFORM_MIF_H -#include "scsc_mif_abs.h" - -enum wlbt_irqs { - PLATFORM_MIF_MBOX, - PLATFORM_MIF_ALIVE, - PLATFORM_MIF_WDOG, -#if defined(CONFIG_SOC_EXYNOS9610) || defined(CONFIG_SOC_EXYNOS9630) || defined(CONFIG_SOC_EXYNOS3830) - PLATFORM_MIF_CFG_REQ, -#endif - /* must be last */ - PLATFORM_MIF_NUM_IRQS -}; - -struct platform_device; - -struct scsc_mif_abs *platform_mif_create(struct platform_device *pdev); -void platform_mif_destroy_platform(struct platform_device *pdev, struct scsc_mif_abs *interface); -struct platform_device *platform_mif_get_platform_dev(struct scsc_mif_abs *interface); -struct device *platform_mif_get_dev(struct scsc_mif_abs *interface); -int platform_mif_suspend(struct scsc_mif_abs *interface); -void platform_mif_resume(struct scsc_mif_abs *interface); - -#endif diff --git a/drivers/misc/samsung/scsc/platform_mif_3830.c b/drivers/misc/samsung/scsc/platform_mif_3830.c deleted file mode 100644 index f2199c4b5e04..000000000000 --- a/drivers/misc/samsung/scsc/platform_mif_3830.c +++ /dev/null @@ -1,2227 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Implements interface */ - -#include "platform_mif.h" - -/* Interfaces it Uses */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_OF -#include -#include -#include -#endif -#include -#include -#include -#include -#include "mif_reg_S5E3830.h" -#include "platform_mif_module.h" -#ifdef CONFIG_ARCH_EXYNOS -#include -#endif -#ifdef CONFIG_SOC_EXYNOS3830 -#include -#endif - -#ifdef CONFIG_SCSC_SMAPPER -#include -#include "mif_reg_smapper.h" -#endif -#ifdef CONFIG_SCSC_QOS -#include -#endif - -#if !defined(CONFIG_SOC_EXYNOS3830) -#error Target processor CONFIG_SOC_EXYNOS3830 not selected -#endif - -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif -/* Time to wait for CFG_REQ IRQ on 3830 */ -#define WLBT_BOOT_TIMEOUT (HZ) - -#ifdef CONFIG_OF_RESERVED_MEM -#include -#endif -static unsigned long sharedmem_base; -static size_t sharedmem_size; - -#ifdef CONFIG_SCSC_CHV_SUPPORT -static bool chv_disable_irq; -module_param(chv_disable_irq, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(chv_disable_irq, "Do not register for irq"); -#endif - -static bool enable_platform_mif_arm_reset = true; -module_param(enable_platform_mif_arm_reset, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_platform_mif_arm_reset, "Enables WIFIBT ARM cores reset"); - -#ifdef CONFIG_SCSC_QOS -struct qos_table { - unsigned int freq_mif; - unsigned int freq_int; - unsigned int freq_cl0; - unsigned int freq_cl1; -}; -#endif - -struct platform_mif { - struct scsc_mif_abs interface; - struct scsc_mbox_s *mbox; - struct platform_device *pdev; - - struct device *dev; - - struct { - int irq_num; - int flags; - atomic_t irq_disabled_cnt; - } wlbt_irq[PLATFORM_MIF_NUM_IRQS]; - - /* MIF registers preserved during suspend */ - struct { - u32 irq_bit_mask; - } mif_preserve; - - /* register MBOX memory space */ - size_t reg_start; - size_t reg_size; - void __iomem *base; - - /* register CMU memory space */ - struct regmap *cmu_base; - - void __iomem *con0_base; - - /* pmu syscon regmap */ - struct regmap *pmureg; -#if defined(CONFIG_SOC_EXYNOS3830) - struct regmap *i3c_apm_pmic; - struct regmap *dbus_baaw; - struct regmap *pbus_baaw; - struct regmap *wlbt_remap; - struct regmap *boot_cfg; - - /* Signalled when CFG_REQ IRQ handled */ - struct completion cfg_ack; - - /* State of CFG_REQ handler */ - enum wlbt_boot_state { - WLBT_BOOT_IN_RESET = 0, - WLBT_BOOT_WAIT_CFG_REQ, - WLBT_BOOT_CFG_DONE, - WLBT_BOOT_CFG_ERROR - } boot_state; - -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER */ - void __iomem *smapper_base; - u8 smapper_banks; - struct { - u8 bank; - u32 ws; - bool large; - struct scsc_mif_smapper_info bank_info; - } *smapper; -#endif - /* Shared memory space - reserved memory */ - unsigned long mem_start; - size_t mem_size; - void __iomem *mem; - - /* Callback function and dev pointer mif_intr manager handler */ - void (*r4_handler)(int irq, void *data); - void *irq_dev; - /* spinlock to serialize driver access */ - spinlock_t mif_spinlock; - void (*reset_request_handler)(int irq, void *data); - void *irq_reset_request_dev; - -#ifdef CONFIG_SCSC_QOS - /* QoS table */ - struct qos_table *qos; - bool qos_enabled; -#endif - /* Suspend/resume handlers */ - int (*suspend_handler)(struct scsc_mif_abs *abs, void *data); - void (*resume_handler)(struct scsc_mif_abs *abs, void *data); - void *suspendresume_data; -}; - -static void power_supplies_on(struct platform_mif *platform); - -extern int mx140_log_dump(void); - -#define platform_mif_from_mif_abs(MIF_ABS_PTR) container_of(MIF_ABS_PTR, struct platform_mif, interface) - -inline void platform_mif_reg_write(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->base + offset); -} - -inline u32 platform_mif_reg_read(struct platform_mif *platform, u16 offset) -{ - return readl(platform->base + offset); -} - -#ifdef CONFIG_SCSC_SMAPPER -inline void platform_mif_reg_write_smapper(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->smapper_base + offset); -} - -inline u32 platform_mif_reg_read_smapper(struct platform_mif *platform, u16 offset) -{ - return readl(platform->smapper_base + offset); -} - -#define PLATFORM_MIF_SHIFT_SMAPPER_ADDR 11 /* From 36 bits addres to 25 bits */ -#define PLATFORM_MIF_SHIFT_SMAPPER_END 4 /* End address aligment */ - -/* Platform is responsible to give the phys mapping of the SMAPPER maps */ -static int platform_mif_smapper_get_mapping(struct scsc_mif_abs *interface, u8 *phy_map, u16 *align) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Mapping %d banks\n", platform->smapper_banks); - - if (!platform->smapper_banks) - return -EINVAL; - - for (i = 0; i < platform->smapper_banks; i++) { - if (platform->smapper[i].large) - phy_map[i] = SCSC_MIF_ABS_LARGE_BANK; - else - phy_map[i] = SCSC_MIF_ABS_SMALL_BANK; - } - - if (align) - *align = 1 << PLATFORM_MIF_SHIFT_SMAPPER_ADDR; - - return 0; -} - -static int platform_mif_smapper_get_bank_info(struct scsc_mif_abs *interface, u8 bank, struct scsc_mif_smapper_info *bank_info) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper_banks) - return -EINVAL; - - bank_info->num_entries = platform->smapper[bank].bank_info.num_entries; - bank_info->mem_range_bytes = platform->smapper[bank].bank_info.mem_range_bytes; - - return 0; -} - -static u8 platform_mif_smapper_granularity_to_bits(u32 granularity) -{ - if (granularity <= 2 * 1024) - return 0; - if (granularity <= 4 * 1024) - return 1; - if (granularity <= 8 * 1024) - return 2; - if (granularity <= 16 * 1024) - return 3; - if (granularity <= 32 * 1024) - return 4; - if (granularity <= 64 * 1024) - return 5; - if (granularity <= 128 * 1024) - return 6; - return 7; -} - -static u32 platform_mif_smapper_get_bank_base_address(struct scsc_mif_abs *interface, u8 bank) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper) - return 0; - - return platform->smapper[bank].ws; -} - -/* Configure smapper according the memory map and range */ -static void platform_mif_smapper_configure(struct scsc_mif_abs *interface, u32 granularity) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u8 gran; - u8 nb = platform->smapper_banks; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Configure SMAPPER with granularity %d\n", granularity); - - gran = platform_mif_smapper_granularity_to_bits(granularity); - - platform_mif_reg_write_smapper(platform, SMAPPER_QCH_DISABLE, 1); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AR, 0); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AW, 0); - /* Program SMAPPER memmap */ - for (i = 0; i < nb; i++) { - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(i), 0); - /* Set START_ADDR */ - platform_mif_reg_write_smapper(platform, START_ADDR(i), platform->smapper[i].ws); - /* Set ADDR_GRANULARITY - FIXED AT 4KB */ - platform_mif_reg_write_smapper(platform, ADDR_GRANULARITY(i), gran); - /* WLAN_ADDR_MAP operation is started */ - } - /* Set access window control (MSB 32bits Start/End address) */ - /* Remapped address should be ranged from AW_START_ADDR to AW_EN_ADDR */ - platform_mif_reg_write_smapper(platform, AW_START_ADDR, 0); - platform_mif_reg_write_smapper(platform, AW_END_ADDR, dma_get_mask(platform->dev) >> PLATFORM_MIF_SHIFT_SMAPPER_END); - smp_mb(); -} - -/* Caller is responsible of validating the phys address (alignment) */ -static int platform_mif_smapper_write_sram(struct scsc_mif_abs *interface, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u32 rb; - - if (!platform->smapper_banks) - return -EINVAL; - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "SMAPPER not enabled\n"); - return -EINVAL; - } - - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 0); - /* Write mapping table to SRAM. Each entry consists of 25 bits MSB address to remap */ - for (i = 0; i < num_entries; i++) { - if (!addr[i]) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ADDR IS NULL at bank %d entry %d/%d\n", bank, first_entry + i, num_entries); - return -EINVAL; - } - /* Set SRAM_WRITE_CTRL to 1'b1*/ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 1); - platform_mif_reg_write_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i), addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - /* check incorrect writings */ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 0); - rb = platform_mif_reg_read_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i)); - if (rb != addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "incorrect mapping detected rb 0x%x, addr 0x%x\n", rb, (u32)addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - return -EFAULT; - } - } - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 1); - smp_mb(); - return 0; -} - -static int platform_mif_parse_smapper(struct platform_mif *platform, struct device_node *np, u8 num_banks) -{ - /* SMAPPER parsing */ - struct device_node *np_banks; - char node_name[50]; - u32 val[2]; - u8 i; - u32 bank = 0, ws = 0, wsz = 0, ent = 0, large = 0; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "banks found: %d szof %zu\n", num_banks, sizeof(*platform->smapper)); - - platform->smapper = kmalloc_array(num_banks, sizeof(*platform->smapper), GFP_KERNEL); - - if (!platform->smapper) - return -ENOMEM; - - for (i = 0; i < num_banks; i++) { - snprintf(node_name, sizeof(node_name), "smapper_bank_%d", i); - np_banks = of_find_node_by_name(np, node_name); - if (!np_banks) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "%s: could not find smapper_bank\n", - node_name); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - of_property_read_u32(np_banks, "bank_num", &bank); - of_property_read_u32(np_banks, "fw_window_start", &ws); - of_property_read_u32(np_banks, "fw_window_size", &wsz); - of_property_read_u32(np_banks, "num_entries", &ent); - of_property_read_u32(np_banks, "is_large", &large); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "bank %d fw_w_start 0x%x fw_w_sz 0x%x entries %d is_large %d\n", - bank, ws, wsz, ent, large); - - platform->smapper[i].bank = (u8)bank; - platform->smapper[i].ws = ws; - platform->smapper[i].large = (bool)large; - platform->smapper[i].bank_info.num_entries = ent; - platform->smapper[i].bank_info.mem_range_bytes = wsz; - } - - /* Update the number of banks before returning */ - platform->smapper_banks = num_banks; - - of_property_read_u32_array(np, "smapper_reg", val, 2); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "smapper reg address 0x%x size 0x%x\n", val[0], val[1]); - platform->smapper_base = - devm_ioremap_nocache(platform->dev, val[0], val[1]); - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping smapper register region\n"); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - - return 0; -} -#endif -#ifdef CONFIG_SCSC_QOS -static int platform_mif_parse_qos(struct platform_mif *platform, struct device_node *np) -{ - int len, i; - - platform->qos_enabled = false; - - len = of_property_count_u32_elems(np, "qos_table"); - if (!(len == 12)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "No qos table for wlbt, or incorrect size\n"); - return -ENOENT; - } - - platform->qos = devm_kzalloc(platform->dev, sizeof(struct qos_table) * len / 4, GFP_KERNEL); - if (!platform->qos) - return -ENOMEM; - - of_property_read_u32_array(np, "qos_table", (unsigned int *)platform->qos, len); - - for (i = 0; i < len / 4; i++) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "QoS Table[%d] mif : %u int : %u cl0 : %u cl1: %u\n", i, - platform->qos[i].freq_mif, - platform->qos[i].freq_int, - platform->qos[i].freq_cl0, - platform->qos[i].freq_cl1); - } - - platform->qos_enabled = true; - return 0; -} - -struct qos_table platform_mif_pm_qos_get_table(struct platform_mif *platform, enum scsc_qos_config config) -{ - struct qos_table table; - - switch (config) { - case SCSC_QOS_MIN: - table.freq_mif = platform->qos[0].freq_mif; - table.freq_int = platform->qos[0].freq_int; - table.freq_cl0 = platform->qos[0].freq_cl0; - table.freq_cl1 = platform->qos[0].freq_cl1; - break; - - case SCSC_QOS_MED: - table.freq_mif = platform->qos[1].freq_mif; - table.freq_int = platform->qos[1].freq_int; - table.freq_cl0 = platform->qos[1].freq_cl0; - table.freq_cl1 = platform->qos[1].freq_cl1; - break; - - case SCSC_QOS_MAX: - table.freq_mif = platform->qos[2].freq_mif; - table.freq_int = platform->qos[2].freq_int; - table.freq_cl0 = platform->qos[2].freq_cl0; - table.freq_cl1 = platform->qos[2].freq_cl1; - break; - - default: - table.freq_mif = 0; - table.freq_int = 0; - table.freq_cl0 = 0; - table.freq_cl1 = 0; - } - - return table; -} - -static int platform_mif_pm_qos_add_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS add request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_add_request(&qos_req->pm_qos_req_mif, PM_QOS_BUS_THROUGHPUT, table.freq_mif); - pm_qos_add_request(&qos_req->pm_qos_req_int, PM_QOS_DEVICE_THROUGHPUT, table.freq_int); - pm_qos_add_request(&qos_req->pm_qos_req_cl0, PM_QOS_CLUSTER0_FREQ_MIN, table.freq_cl0); - pm_qos_add_request(&qos_req->pm_qos_req_cl1, PM_QOS_CLUSTER1_FREQ_MIN, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_update_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS update request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_update_request(&qos_req->pm_qos_req_mif, table.freq_mif); - pm_qos_update_request(&qos_req->pm_qos_req_int, table.freq_int); - pm_qos_update_request(&qos_req->pm_qos_req_cl0, table.freq_cl0); - pm_qos_update_request(&qos_req->pm_qos_req_cl1, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_remove_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform) - return -ENODEV; - - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS remove request\n"); - pm_qos_remove_request(&qos_req->pm_qos_req_mif); - pm_qos_remove_request(&qos_req->pm_qos_req_int); - pm_qos_remove_request(&qos_req->pm_qos_req_cl0); - pm_qos_remove_request(&qos_req->pm_qos_req_cl1); - - return 0; -} -#endif - -static void platform_mif_irq_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT handler not registered\n"); -} - -static void platform_mif_irq_reset_request_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT reset_request handler not registered\n"); -} - -irqreturn_t platform_mif_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "INT %pS\n", platform->r4_handler); - if (platform->r4_handler != platform_mif_irq_default_handler) - platform->r4_handler(irq, platform->irq_dev); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MIF Interrupt Handler not registered\n"); - - return IRQ_HANDLED; -} - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ -irqreturn_t platform_alive_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - - return IRQ_HANDLED; -} -#endif - -irqreturn_t platform_wdog_isr(int irq, void *data) -{ - //int ret = 0; - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - if (platform->reset_request_handler != platform_mif_irq_reset_request_default_handler) { - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - platform->reset_request_handler(irq, platform->irq_reset_request_dev); - } else { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG Interrupt reset_request_handler not registered\n"); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Disabling unhandled WDOG IRQ.\n"); - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_inc(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt); - } - - /* TODO: need to find correct register to set here */ -#if 0 - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_RESET_REQ_CLR, WLBT_RESET_REQ_CLR); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clearing WLBT_RESET_REQ\n"); - if (ret < 0) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_RESET_REQ_CLR]: %d\n", ret); -#endif - - return IRQ_HANDLED; -} - -/* - * Attached array contains the replacement PMU boot code which should - * be programmed using the CBUS during the config phase. - */ -uint32_t ka_patch[] = { - // Maxwell142 PMU+PROC combined boot ROM - // IP Version: 0xFF - // Major Version: 0xF, Minor Version: 0xF - // PMU ROM version: 0x2 - // PROC ROM version: 0x0 - // received initial version on 030719 - 0x90750002, - 0x11a4c218, - 0x755a118a, - 0x9075e090, - 0x30b3e5e7, - 0xa230f8e0, - 0xf5077411, - 0xfdb2b5b1, - 0x7400b153, - 0xb5acf507, - 0xb475fdad, - 0x20b3e501, - 0xb475fbe0, - 0x75a3d200, - 0xd2801890, - 0x7907a075, - 0xe6b07837, - 0x07b40754, - 0xd90b8002, - 0xf5c404f6, - 0x00af7590, - 0x90750380, - 0xf7532290, - 0xeff753f7, - 0x53dff753, - 0x0479fece, - 0xce53fed9, - 0xd90c79fd, - 0xfbce53fe, - 0x53159275, - 0xce53fd91, - 0x02f943f7, - 0x22fef953, - 0xd8fed9f9, - 0x9e7522fb, - 0xcfc17501, - 0x75a4c275, - 0xc4754ac3, - 0xa4c57547, - 0x7561c675, - 0xd27540c7, - 0x80d37503, - 0x7500c975, - 0xcb75d0ca, - 0x00cc7500, - 0x75009a75, - 0x9c75c09b, - 0x009d7500, - 0x82740278, - 0x43848012, - 0x057802c6, - 0x8012d074, - 0x20c34384, - 0x75d09075, - 0x93750291, - 0x029e7501, - 0x00000022, -}; - -irqreturn_t platform_cfg_req_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - u64 ret64 = 0; - const u64 EXYNOS_WLBT = 0x1; - /*s32 ret = 0;*/ - unsigned int ka_addr = 0x1000; - uint32_t *ka_patch_addr = ka_patch; - //u32 id; - -#define CHECK(x) do { \ - int retval = (x); \ - if (retval < 0) {\ - pr_err("%s failed at L%d", __FUNCTION__, __LINE__); \ - goto cfg_error; \ - } \ -} while (0) - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "disable_irq\n"); - - /* mask the irq */ - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - /* Was the CFG_REQ irq received from WLBT before we expected it? - * Typically this indicates an issue returning WLBT HW to reset. - */ - if (platform->boot_state != WLBT_BOOT_WAIT_CFG_REQ) { - u32 val; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Spurious CFG_REQ IRQ from WLBT!\n"); - - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_NS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_S 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - return IRQ_HANDLED; - } - - /* Set TZPC to non-secure mode */ - ret64 = exynos_smc(SMC_CMD_CONN_IF, (EXYNOS_WLBT << 32) | EXYNOS_SET_CONN_TZPC, 0, 0); - if (ret64) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to set TZPC to non-secure mode: %llu\n", ret64); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SMC_CMD_CONN_IF run successfully : %llu\n", ret64); - - /* WLBT_REMAP PMU_REMAP */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP begin\n"); - CHECK(regmap_write(platform->wlbt_remap, 0x400, WLBT_DBUS_BAAW_0_START >> 12)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP end\n"); - - /* DBUS_BAAW regions */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW begin\n"); // PMU_DBUS_BAAW - - /* Shared DRAM mapping. The destination address is the location reserved - * by the kernel. - */ - CHECK(regmap_write(platform->dbus_baaw, 0x0, WLBT_DBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x4, WLBT_DBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x8, platform->mem_start >> 12)); // FW AP base addr >> 12 - CHECK(regmap_write(platform->dbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); -#if 0 - /* Additional DRAM mappings for future use */ - CHECK(regmap_write(platform->dbus_baaw, 0x10, 0x000C0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x14, 0x000D0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x18, 0x000D0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x1C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->dbus_baaw, 0x20, 0x000D0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x24, 0x000E0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x28, 0x000E0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x2C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->dbus_baaw, 0x30, 0x000E0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x34, 0x000F0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x38, 0x000F0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x3C, WLBT_BAAW_ACCESS_CTRL)); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW end\n"); - - /* PBUS_BAAW regions */ - /* ref wlbt_if_S5E3830.c, updated for MX152 memory map */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW begin\n"); - - /* Range for CP2WLBT mailbox */ - CHECK(regmap_write(platform->pbus_baaw, 0x0, WLBT_CBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4, WLBT_CBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x8, WLBT_PBUS_MBOX_CP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); - - /* Range includes AP2WLBT,APM2WLBT,GNSS2WLBT mailboxes */ - CHECK(regmap_write(platform->pbus_baaw, 0x10, WLBT_CBUS_BAAW_1_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x14, WLBT_CBUS_BAAW_1_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x18, WLBT_PBUS_MBOX_GNSS2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x1C, WLBT_BAAW_ACCESS_CTRL)); -#if 0 - /* These mappings are not yet used by WLBT FW */ - CHECK(regmap_write(platform->pbus_baaw, 0x20, WLBT_CBUS_BAAW_2_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x24, WLBT_CBUS_BAAW_2_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x28, WLBT_PBUS_MBOX_APM2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x2C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x30, WLBT_CBUS_BAAW_3_START >>12)); - CHECK(regmap_write(platform->pbus_baaw, 0x34, WLBT_CBUS_BAAW_3_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x38, WLBT_PBUS_MBOX_AP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x3C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x40, WLBT_CBUS_BAAW_4_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x44, WLBT_CBUS_BAAW_4_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x48, WLBT_PBUS_MBOX_WLBT2ABOX_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x50, WLBT_CBUS_BAAW_5_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x54, WLBT_CBUS_BAAW_5_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x58, WLBT_PBUS_MBOX_WLBT2CHUB_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x5C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x60, WLBT_CBUS_BAAW_6_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x64, WLBT_CBUS_BAAW_6_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x68, WLBT_PBUS_CHUB_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x6C, WLBT_BAAW_ACCESS_CTRL)); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW end\n"); - - /* PMU boot patch - * BOOT_SOURCE_CFG 0x0001 KA RAM access granted to CFG longhop. Any 8051 accesses are waited if this setting is used. - */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT begin\n"); - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x1)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT done\n"); - - while (ka_patch_addr < (ka_patch + ARRAY_SIZE(ka_patch))) { - CHECK(regmap_write(platform->boot_cfg, ka_addr, *ka_patch_addr)); - ka_addr += sizeof(ka_patch[0]); - ka_patch_addr++; - } - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "KA patch done\n"); - - /* Notify PMU of configuration done - * BOOT_SOURCE_ROM 0x0000 KA RAM access granted to 8051. CBUS accesses are ignored if this setting is used. - */ - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x0)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT config done\n"); - - /* BOOT_CFG_ACK is 1-bit wide */ - CHECK(regmap_write(platform->boot_cfg, 0x4, 0x1)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_CFG_ACK done\n"); - - /* Mark as CFQ_REQ handled, so boot may continue */ - platform->boot_state = WLBT_BOOT_CFG_DONE; - - /* Signal triggering function that the IRQ arrived and CFG was done */ - complete(&platform->cfg_ack); - - /* Re-enable IRQ here to allow spurious interrupt to be tracked */ - enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - /* as per wlbt_if_S5E3830.c - end */ - - return IRQ_HANDLED; -cfg_error: - platform->boot_state = WLBT_BOOT_CFG_ERROR; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ERROR: WLBT Config failed. WLBT will not work\n"); - complete(&platform->cfg_ack); - return IRQ_HANDLED; -} - -static void platform_mif_unregister_irq(struct platform_mif *platform) -{ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering IRQs\n"); - - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform); - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform); - /* Reset irq_disabled_cnt for WDOG IRQ since the IRQ itself is here unregistered and disabled */ - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* if ALIVE irq is required */ - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform); -#endif - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform); -} - -static int platform_mif_register_irq(struct platform_mif *platform) -{ - int err; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering IRQs\n"); - - /* Register MBOX irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering MBOX irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform->wlbt_irq[PLATFORM_MIF_MBOX].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform_mif_isr, - platform->wlbt_irq[PLATFORM_MIF_MBOX].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register MBOX handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - - /* Register WDOG irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering WDOG irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform->wlbt_irq[PLATFORM_MIF_WDOG].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform_wdog_isr, - platform->wlbt_irq[PLATFORM_MIF_WDOG].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register WDOG handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* Register ALIVE irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering ALIVE irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform_alive_isr, - platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags, DRV_NAME, platform); - if (IS_ERR_VALUE(err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register ALIVE handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } -#endif - - /* Mark as WLBT in reset before enabling IRQ to guard against spurious IRQ */ - platform->boot_state = WLBT_BOOT_IN_RESET; - smp_wmb(); /* commit before irq */ - - /* Register WB2AP_CFG_REQ irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering CFG_REQ irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform_cfg_req_isr, - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register CFG_REQ handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - - /* Leave disabled until ready to handle */ - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - return 0; -} - -static void platform_mif_destroy(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - platform_mif_unregister_irq(platform); -} - -static char *platform_mif_get_uid(struct scsc_mif_abs *interface) -{ - /* Avoid unused parameter error */ - (void)interface; - return "0"; -} - -static void wlbt_regdump(struct platform_mif *platform) -{ - u32 val = 0; - - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_S 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CONFIGURATION 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_NS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_IN, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_IN 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_OUT, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_OUT 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATUS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_STATES, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATES 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); -} - -/* WLBT START */ -static int platform_mif_start(struct scsc_mif_abs *interface, bool start) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "start %d\n", start); - /* At this point WLBT should assert the CFG_REQ IRQ, so wait for it */ - if (start && - wait_for_completion_timeout(&platform->cfg_ack, WLBT_BOOT_TIMEOUT) == 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Timeout waiting for CFG_REQ IRQ\n"); - wlbt_regdump(platform); - return -ETIMEDOUT; - } - - wlbt_regdump(platform); - - /* only continue if CFG_REQ IRQ configured WLBT/PMU correctly */ - if (platform->boot_state == WLBT_BOOT_CFG_ERROR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "CFG_REQ failed to configure WLBT.\n"); - return -EIO; - } - return 0; -} - -static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - int ret = 0; - u32 val = 0; - u32 v = 0; - unsigned long timeout; - static bool init_done; - - /* We're now ready for the IRQ */ - platform->boot_state = WLBT_BOOT_WAIT_CFG_REQ; - smp_wmb(); /* commit before irq */ - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "on boot_state = WLBT_BOOT_WAIT_CFG_REQ\n"); - - /* INIT SEQUENCE - First WLBT boot only - * Cold reset wrt. AP power sequencer, cold reset for WLBT - */ - if (!init_done) { - /* init sequence from excite - PMUCAL - * SetBits((uinteger)REG_WLBT_CTRL_S, WLBT_CTRL_S_START_POS, 0x1, 0x1); - * SetBits((uinteger)REG_WLBT_OPTION, 3, 0x1, 0x1); - * udelay(1000); - * SetBits((uinteger)REG_TOP_OUT, 1, 0x1, 0x1); - * while (GetBits((uinteger)REG_VGPIO_TX_MONITOR, 29, 0x1) != 1) - * ; - * SetBits((uinteger)REG_WLBT_CONFIGURATION, WLBT_CONFIGURATION_LOCAL_PWR_CFG_POS, 0x1, 0x1); - * while (GetBits((uinteger)REG_WLBT_STATUS, 0, 0x1) != WLBT_STATUS_STATUS_POWERON) - * ; - * SetBits((uinteger)REG_WLBT_CTRL_NS, WLBT_CTRL_NS_ACTIVE_CLR_POS, 0x1, 0x0); - * SetBits((uinteger)REG_WLBT_CTRL_NS, WLBT_CTRL_NS_ACTIVE_EN_POS, 0x1, 0x1); - * - */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "init\n"); - - /* WLBT_CTRL_S[WLBT_START] = 1 enable */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S, - WLBT_START, WLBT_START); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CTRL_S[WLBT_START]: 0x%x\n", val); - - /* WLBT_OPTION[WLBT_OPTION_DATA] = 1 Power On */ - ret = regmap_update_bits(platform->pmureg, WLBT_OPTION, - WLBT_OPTION_DATA, WLBT_OPTION_DATA); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_OPTION[WLBT_OPTION_DATA]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_OPTION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_OPTION[WLBT_OPTION_DATA]: 0x%x\n", val); - - /* TOP_OUT[PWRRGTON_CP] = 1 Power On */ - ret = regmap_update_bits(platform->pmureg, TOP_OUT, - PWRRGTON_CP, PWRRGTON_CP); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update TOP_OUT[PWRRGTON_CP]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, TOP_OUT, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully TOP_OUT[PWRRGTON_CP]: 0x%x\n", val); - - /* VGPIO_TX_MONITOR = 0x1 */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - val &= (u32)VGPIO_TX_MON_BIT29; - if (val) { - SCSC_TAG_INFO(PLAT_MIF, "VGPIO_TX_MONITOR 0x%x\n", val); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for VGPIO_TX_MONITOR time-out: " - "VGPIO_TX_MONITOR 0x%x\n", val); - } - - /* WLBT_CONFIGURATION[LOCAL_PWR_CFG] = 1 Power On */ - ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION, - LOCAL_PWR_CFG, 0x1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CONFIGURATION[LOCAL_PWR_CFG]: 0x%x\n", val); - - /* wait for power up complete WLBT_STATUS[WLBT_STATUS_BIT0] = 1 for Power On */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - val &= (u32)WLBT_STATUS_BIT0; - if (val) { - /* Power On complete */ - SCSC_TAG_INFO(PLAT_MIF, "Power On complete: WLBT_STATUS 0x%x\n", val); - /* re affirming power on by reading WLBT_STATES */ - /* STATES[7:0] = 0x10 for Power Up */ - regmap_read(platform->pmureg, WLBT_STATES, &v); - SCSC_TAG_INFO(PLAT_MIF, "Power On complete: WLBT_STATES 0x%x\n", v); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for power on time-out: " - "WLBT_STATUS 0x%x, WLBT_STATES 0x%x\n", val, v); - } - - /* WLBT_CTRL_NS[WLBT_ACTIVE_CLR] = 0 Active interrupt clear */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_ACTIVE_CLR, 0x0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: 0x%x\n", val); - - /* WLBT_CTRL_NS[WLBT_ACTIVE_EN] = 1 Active interrupt enable */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_ACTIVE_EN, WLBT_ACTIVE_EN); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_EN]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CTRL_NS[WLBT_ACTIVE_EN]: 0x%x\n", val); - - init_done = true; - - goto init_code_done; - } - - /* RESET RELEASE - Subsequent WLBT reboots */ - /* wlbt_if_reset_release - from excite code - * SetBits((uinteger)REG_WLBT_CONFIGURATION, WLBT_CONFIGURATION_LOCAL_PWR_CFG_POS, 0x1, 0x1); - * while (GetBits((uinteger)REG_WLBT_STATUS, WLBT_STATUS_STATUS_POS, 0x1) != WLBT_STATUS_STATUS_POWERON) - * ; - * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_PWR_REQ__F_POS, 0x1, 0x1); - * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_TCXO_REQ__F_POS, 0x1, 0x1); - * udelay(2000); - * */ - - /* Warm reset wrt. AP power sequencer, but cold reset for WLBT */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "release\n"); - - /* Power Up */ - ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION, - LOCAL_PWR_CFG, 0x1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CONFIGURATION[LOCAL_PWR_CFG]: 0x%x\n", val); - - /* wait for power up complete WLBT_STATUS[0] = 0 for power down */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - val &= (u32)WLBT_STATUS_BIT0; - if (val) { - /* Power up complete */ - SCSC_TAG_INFO(PLAT_MIF, "Power up complete: WLBT_STATUS 0x%x\n", val); - /* re affirming power down by reading WLBT_STATES */ - /* STATES[7:0] = 0x10 for Power Up */ - regmap_read(platform->pmureg, WLBT_STATES, &v); - SCSC_TAG_INFO(PLAT_MIF, "Power up complete: WLBT_STATES 0x%x\n", v); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "Timeout waiting for Power up complete: " - "WLBT_STATUS 0x%x, WLBT_STATES 0x%x\n", val, v); - } - - /* enable PWR_REQ_F and TCXO_REQ_F interrupts */ - ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN, - PWR_REQ_F, PWR_REQ_F); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_INT_EN[PWR_REQ_F]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_INT_EN, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_INT_EN[PWR_REQ_F]: 0x%x\n", val); - - ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN, - TCXO_REQ_F, TCXO_REQ_F); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_INT_EN[TCXO_REQ_F]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_INT_EN, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_INT_EN[TCXO_REQ_F]: 0x%x\n", val); - -init_code_done: - /* Now handle the CFG_REQ IRQ */ - enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - ret = platform_mif_start(interface, true); - if (ret) - return ret; - - return ret; -} - -static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long timeout; - int ret; - u32 val; - - /* wlbt_if_reset_assertion() - from wlbt_if_S5E3830.c - PMUCAL - * SetBits((uinteger)REG_WLBT_OPTION, 3, 0x1, 0x1); - * SetBits((uinteger)REG_MIF_CTRL, MIF_CTRL_TCXO_EN_POS, 0x1, 0x1); - * SetBits((uinteger)REG_TCXO_BUF_CTRL, TCXO_BUF_CTRL_BIAS_EN_POS, 0x1, 0x1); - * SetBits((uinteger)REG_TOP_OUT, TOP_OUT_PWRRGTON_CP_POS, 0x1, 0x1); - * while (GetBits((uinteger)REG_VGPIO_TX_MONITOR, 29, 0x1) != 1) - * ; - * udelay(1000); //1 msec wait??? - * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_PWR_REQ__F_POS, 0x00000001, 0x00000000); - * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_TCXO_REQ__F_POS, 0x00000001, 0x00000000); - * SetBits((uinteger)REG_WLBT_CTRL_NS, WLBT_CTRL_NS_ACTIVE_EN_POS, 0x1, 0x0); - * SetBits((uinteger)REG_WLBT_CONFIGURATION, WLBT_CONFIGURATION_LOCAL_PWR_CFG_POS, 0x1, 0x0); - * while (GetBits((uinteger)REG_WLBT_STATUS, WLBT_STATUS_STATUS_POS, 0x1) != WLBT_STATUS_STATUS_POWERDOWN) - */ - - /* WLBT_OPTION[WLBT_OPTION_DATA] = 1 Power On */ - ret = regmap_update_bits(platform->pmureg, WLBT_OPTION, - WLBT_OPTION_DATA, WLBT_OPTION_DATA); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_OPTION[WLBT_OPTION_DATA]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_OPTION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_OPTION[WLBT_OPTION_DATA]: 0x%x\n", val); - - ret = regmap_update_bits(platform->pmureg, MIF_CTRL, - TCXO_EN, TCXO_EN); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update MIF_CTRL[TCXO_EN]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, TCXO_BUF_CTRL, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully MIF_CTRL[TCXO_EN]: 0x%x\n", val & TCXO_EN); - - ret = regmap_update_bits(platform->pmureg, TCXO_BUF_CTRL, - TCXO_BUF_BIAS_EN_WLBT, TCXO_BUF_BIAS_EN_WLBT); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update TCXO_BUF_CTRL[TCXO_BUF_BIAS_EN_WLBT]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, TCXO_BUF_CTRL, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully TCXO_BUF_CTRL[TCXO_BUF_BIAS_EN_WLBT]: 0x%x\n", val & TCXO_BUF_BIAS_EN_WLBT); - - ret = regmap_update_bits(platform->pmureg, TOP_OUT, - PWRRGTON_CP, PWRRGTON_CP); - - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update TOP_OUT[PWRRGTON_CP]: %d\n", ret); - return ret; - } - /* VGPIO_TX_MONITOR = 0x1 */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - val &= (u32)VGPIO_TX_MON_BIT29; - if (val) { - SCSC_TAG_INFO(PLAT_MIF, "VGPIO_TX_MONITOR 0x%x\n", val); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for VGPIO_TX_MONITOR time-out: " - "VGPIO_TX_MONITOR 0x%x\n", val); - } - - regmap_read(platform->pmureg, TCXO_BUF_CTRL, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully TOP_OUT[PWRRGTON_CP]: 0x%x\n", val & PWRRGTON_CP); - - udelay(1000); - - /* disable PWR_REQ_F and TCXO_REQ_F interrupts */ - ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN, - PWR_REQ_F, 0x0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_INT_EN[PWR_REQ_F]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_INT_EN, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_INT_EN[PWR_REQ_F]: 0x%x\n", val); - - ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN, - TCXO_REQ_F, 0x0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_INT_EN[TCXO_REQ_F]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_INT_EN, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_INT_EN[TCXO_REQ_F]: 0x%x\n", val); - - /* Active interrupt disable */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_ACTIVE_EN, 0x0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_EN]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CTRL_NS[WLBT_ACTIVE_EN]: 0x%x\n", val); - - /* Power Down */ - ret = regmap_write_bits(platform->pmureg, WLBT_CONFIGURATION, - LOCAL_PWR_CFG, 0x0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CONFIGURATION[LOCAL_PWR_CFG]: 0x%x\n", val); - - /* Wait for power Off WLBT_STATUS[WLBT_STATUS_BIT0] = 0 */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - val &= (u32)WLBT_STATUS_BIT0; - if (val == 0) { - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATUS 0x%x\n", val); - /* re affirming power down by reading WLBT_STATES */ - /* STATES[7:0] = 0x80 for Power Down */ - regmap_read(platform->pmureg, WLBT_STATES, &val); - SCSC_TAG_INFO(PLAT_MIF, "Power down complete: WLBT_STATES 0x%x\n", val); - - return 0; /* OK - return */ - } - } while (time_before(jiffies, timeout)); - - /* Timed out */ - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Timeout waiting for WLBT_STATUS status\n"); - - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_STATES, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATES 0x%x\n", val); - return -ETIME; -} - -/* reset=0 - release from reset */ -/* reset=1 - hold reset */ -static int platform_mif_reset(struct scsc_mif_abs *interface, bool reset) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 ret = 0; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (enable_platform_mif_arm_reset || !reset) { - if (!reset) { /* Release from reset */ -#ifdef CONFIG_ARCH_EXYNOS - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SOC_VERSION: product_id 0x%x, rev 0x%x\n", - exynos_soc_info.product_id, exynos_soc_info.revision); -#endif - power_supplies_on(platform); - - ret = platform_mif_pmu_reset_release(interface); - } else { - /* Put back into reset */ - ret = platform_mif_pmu_reset_assert(interface); - } - } else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Not resetting ARM Cores - enable_platform_mif_arm_reset: %d\n", - enable_platform_mif_arm_reset); - return ret; -} - -static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size) -{ - int i; - struct page **pages; - void *vmem; - - size = PAGE_ALIGN(size); - - pages = kmalloc((size >> PAGE_SHIFT) * sizeof(*pages), GFP_KERNEL); - if (!pages) - return NULL; - - /* Map NORMAL_NC pages with kernel virtual space */ - for (i = 0; i < (size >> PAGE_SHIFT); i++) { - pages[i] = phys_to_page(phys_addr); - phys_addr += PAGE_SIZE; - } - - vmem = vmap(pages, size >> PAGE_SHIFT, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); - - kfree(pages); - return (void __iomem *)vmem; -} - -static void platform_mif_unmap_region(void *vmem) -{ - vunmap(vmem); -} - -static void *platform_mif_map(struct scsc_mif_abs *interface, size_t *allocated) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - if (allocated) - *allocated = 0; - - platform->mem = - platform_mif_map_region(platform->mem_start, platform->mem_size); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Error remaping shared memory\n"); - return NULL; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Map: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - - /* Initialise MIF registers with documented defaults */ - /* MBOXes */ - for (i = 0; i < NUM_MBOX_PLAT; i++) - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(ISSR(i)), 0x00000000); - - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); - -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_disable_irq == true) { - if (allocated) - *allocated = platform->mem_size; - return platform->mem; - } -#endif - /* register interrupts */ - if (platform_mif_register_irq(platform)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - return NULL; - } - - if (allocated) - *allocated = platform->mem_size; - /* Set the CR4 base address in Mailbox??*/ - return platform->mem; -} - -/* HERE: Not sure why mem is passed in - its stored in platform - as it should be */ -static void platform_mif_unmap(struct scsc_mif_abs *interface, void *mem) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - /* Avoid unused parameter error */ - (void)mem; - - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); - -#ifdef CONFIG_SCSC_CHV_SUPPORT - /* Restore PIO changed by Maxwell subsystem */ - if (chv_disable_irq == false) - /* Unregister IRQs */ - platform_mif_unregister_irq(platform); -#else - platform_mif_unregister_irq(platform); -#endif - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - platform->mem = NULL; -} - -static u32 platform_mif_irq_bit_mask_status_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INTMR0: 0x%x\n", val); - return val; -} - -static u32 platform_mif_irq_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - /* Function has to return the interrupts that are enabled *AND* not masked */ - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INT-INTMSR0: 0x%x\n", val); - - return val; -} - -static void platform_mif_irq_bit_set(struct scsc_mif_abs *interface, int bit_num, enum scsc_mif_abs_target target) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 reg; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - - reg = INTGR1; - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(reg), (1 << bit_num)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTGR1: bit %d on target %d\n", bit_num, target); -} - -static void platform_mif_irq_bit_clear(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - /* WRITE : 1 = Clears Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), ((1 << bit_num) << 16)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTCR0: bit %d\n", bit_num); -} - -static void platform_mif_irq_bit_mask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 1 = Mask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val | ((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTMR0: 0x%x bit %d\n", val | (1 << bit_num), bit_num); -} - -static void platform_mif_irq_bit_unmask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 0 = Unmask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val & ~((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "UNMASK Setting INTMR0: 0x%x bit %d\n", val & ~((1 << bit_num) << 16), bit_num); -} - -/* Return the contents of the mask register */ -static u32 __platform_mif_irq_bit_mask_read(struct platform_mif *platform) -{ - u32 val; - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Read INTMR0: 0x%x\n", val); - - return val; -} - -/* Write the mask register, destroying previous contents */ -static void __platform_mif_irq_bit_mask_write(struct platform_mif *platform, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Write INTMR0: 0x%x\n", val); -} - -static void platform_mif_irq_reg_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif int handler %pS in %p %p\n", handler, platform, interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = handler; - platform->irq_dev = dev; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif int handler %pS\n", interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_reg_reset_request_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif reset_request int handler %pS in %p %p\n", handler, platform, interface); - platform->reset_request_handler = handler; - platform->irq_reset_request_dev = dev; - if (atomic_read(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "Default WDOG handler disabled by spurios IRQ...re-enabling.\n"); - enable_irq(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); - } -} - -static void platform_mif_irq_unreg_reset_request_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "UnRegistering mif reset_request int handler %pS\n", interface); - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; -} - -static void platform_mif_suspend_reg_handler(struct scsc_mif_abs *interface, - int (*suspend)(struct scsc_mif_abs *abs, void *data), - void (*resume)(struct scsc_mif_abs *abs, void *data), - void *data) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = suspend; - platform->resume_handler = resume; - platform->suspendresume_data = data; -} - -static void platform_mif_suspend_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; -} - -static u32 *platform_mif_get_mbox_ptr(struct scsc_mif_abs *interface, u32 mbox_index) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 *addr; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "mbox_index 0x%x\n", mbox_index); - addr = platform->base + MAILBOX_WLBT_REG(ISSR(mbox_index)); - return addr; -} - -static int platform_mif_get_mifram_ref(struct scsc_mif_abs *interface, void *ptr, scsc_mifram_ref *ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return -ENOMEM; - } - - /* Check limits! */ - if (ptr >= (platform->mem + platform->mem_size)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Unable to get pointer reference\n"); - return -ENOMEM; - } - - *ref = (scsc_mifram_ref)((uintptr_t)ptr - (uintptr_t)platform->mem); - - return 0; -} - -static void *platform_mif_get_mifram_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - /* Check limits */ - if (ref >= 0 && ref < platform->mem_size) - return (void *)((uintptr_t)platform->mem + (uintptr_t)ref); - else - return NULL; -} - -static void *platform_mif_get_mifram_phy_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem_start) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - return (void *)((uintptr_t)platform->mem_start + (uintptr_t)ref); -} - -static uintptr_t platform_mif_get_mif_pfn(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - return vmalloc_to_pfn(platform->mem); -} - -static struct device *platform_mif_get_mif_device(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - return platform->dev; -} - -static void platform_mif_irq_clear(void) -{ - /* Implement if required */ -} - -static int platform_mif_read_register(struct scsc_mif_abs *interface, u64 id, u32 *val) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (id == SCSC_REG_READ_WLBT_STAT) { - regmap_read(platform->pmureg, WLBT_STAT, val); - return 0; - } - - return -EIO; -} - -static void platform_mif_dump_register(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR1))); - - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_cleanup(struct scsc_mif_abs *interface) -{ -} - -static void platform_mif_restart(struct scsc_mif_abs *interface) -{ -} - -#ifdef CONFIG_OF_RESERVED_MEM -static int __init platform_mif_wifibt_if_reserved_mem_setup(struct reserved_mem *remem) -{ - SCSC_TAG_DEBUG(PLAT_MIF, "memory reserved: mem_base=%#lx, mem_size=%zd\n", - (unsigned long)remem->base, (size_t)remem->size); - - sharedmem_base = remem->base; - sharedmem_size = remem->size; - return 0; -} -RESERVEDMEM_OF_DECLARE(wifibt_if, "exynos,wifibt_if", platform_mif_wifibt_if_reserved_mem_setup); -#endif - -struct scsc_mif_abs *platform_mif_create(struct platform_device *pdev) -{ - struct scsc_mif_abs *platform_if; - struct platform_mif *platform = - (struct platform_mif *)devm_kzalloc(&pdev->dev, sizeof(struct platform_mif), GFP_KERNEL); - int err = 0; - u8 i = 0; - struct resource *reg_res; - -#ifdef CONFIG_SCSC_SMAPPER - u32 smapper_banks = 0; -#endif - - if (!platform) - return NULL; - - SCSC_TAG_INFO_DEV(PLAT_MIF, &pdev->dev, "Creating MIF platform device\n"); - - platform_if = &platform->interface; - - /* initialise interface structure */ - platform_if->destroy = platform_mif_destroy; - platform_if->get_uid = platform_mif_get_uid; - platform_if->reset = platform_mif_reset; - platform_if->map = platform_mif_map; - platform_if->unmap = platform_mif_unmap; - platform_if->irq_bit_set = platform_mif_irq_bit_set; - platform_if->irq_get = platform_mif_irq_get; - platform_if->irq_bit_mask_status_get = platform_mif_irq_bit_mask_status_get; - platform_if->irq_bit_clear = platform_mif_irq_bit_clear; - platform_if->irq_bit_mask = platform_mif_irq_bit_mask; - platform_if->irq_bit_unmask = platform_mif_irq_bit_unmask; - platform_if->irq_reg_handler = platform_mif_irq_reg_handler; - platform_if->irq_unreg_handler = platform_mif_irq_unreg_handler; - platform_if->irq_reg_reset_request_handler = platform_mif_irq_reg_reset_request_handler; - platform_if->irq_unreg_reset_request_handler = platform_mif_irq_unreg_reset_request_handler; - platform_if->suspend_reg_handler = platform_mif_suspend_reg_handler; - platform_if->suspend_unreg_handler = platform_mif_suspend_unreg_handler; - platform_if->get_mbox_ptr = platform_mif_get_mbox_ptr; - platform_if->get_mifram_ptr = platform_mif_get_mifram_ptr; - platform_if->get_mifram_ref = platform_mif_get_mifram_ref; - platform_if->get_mifram_pfn = platform_mif_get_mif_pfn; - platform_if->get_mifram_phy_ptr = platform_mif_get_mifram_phy_ptr; - platform_if->get_mif_device = platform_mif_get_mif_device; - platform_if->irq_clear = platform_mif_irq_clear; - platform_if->mif_dump_registers = platform_mif_dump_register; - platform_if->mif_read_register = platform_mif_read_register; - platform_if->mif_cleanup = platform_mif_cleanup; - platform_if->mif_restart = platform_mif_restart; -#ifdef CONFIG_SCSC_SMAPPER - platform_if->mif_smapper_get_mapping = platform_mif_smapper_get_mapping; - platform_if->mif_smapper_get_bank_info = platform_mif_smapper_get_bank_info; - platform_if->mif_smapper_write_sram = platform_mif_smapper_write_sram; - platform_if->mif_smapper_configure = platform_mif_smapper_configure; - platform_if->mif_smapper_get_bank_base_address = platform_mif_smapper_get_bank_base_address; -#endif -#ifdef CONFIG_SCSC_QOS - platform_if->mif_pm_qos_add_request = platform_mif_pm_qos_add_request; - platform_if->mif_pm_qos_update_request = platform_mif_pm_qos_update_request; - platform_if->mif_pm_qos_remove_request = platform_mif_pm_qos_remove_request; -#endif - /* Update state */ - platform->pdev = pdev; - platform->dev = &pdev->dev; - - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; - -#ifdef CONFIG_OF_RESERVED_MEM - platform->mem_start = sharedmem_base; - platform->mem_size = sharedmem_size; -#else - /* If CONFIG_OF_RESERVED_MEM is not defined, sharedmem values should be - * parsed from the scsc_wifibt binding - */ - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-base", &sharedmem_base)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_start = sharedmem_base; - - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-size", &sharedmem_size)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_size = sharedmem_size; -#endif -#ifdef CONFIG_SCSC_SMAPPER - platform->smapper = NULL; -#endif - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->mem_start 0x%x platform->mem_size 0x%x\n", - (u32)platform->mem_start, (u32)platform->mem_size); - if (platform->mem_start == 0) - SCSC_TAG_WARNING_DEV(PLAT_MIF, platform->dev, "platform->mem_start is 0"); - - if (platform->mem_size == 0) { - /* We return return if mem_size is 0 as it does not make any sense. - * This may be an indication of an incorrect platform device binding. - */ - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "platform->mem_size is 0"); - err = -EINVAL; - goto error_exit; - } - - /* Memory resource - Phys Address of MAILBOX_WLBT register map */ - reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!reg_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error getting mem resource for MAILBOX_WLBT\n"); - err = -ENOENT; - goto error_exit; - } - - platform->reg_start = reg_res->start; - platform->reg_size = resource_size(reg_res); - - platform->base = - devm_ioremap_nocache(platform->dev, reg_res->start, resource_size(reg_res)); - - if (!platform->base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping register region\n"); - err = -EBUSY; - goto error_exit; - } - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->reg_start %lx size %x base %p\n", - (uintptr_t)platform->reg_start, (u32)platform->reg_size, platform->base); - - /* Get the 4 IRQ resources */ - for (i = 0; i < 4; i++) { - struct resource *irq_res; - int irqtag; - - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!irq_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "No IRQ resource at index %d\n", i); - err = -ENOENT; - goto error_exit; - } - - if (!strcmp(irq_res->name, "MBOX")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MBOX irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_MBOX; - } else if (!strcmp(irq_res->name, "ALIVE")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "ALIVE irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_ALIVE; - } else if (!strcmp(irq_res->name, "WDOG")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_WDOG; - } else if (!strcmp(irq_res->name, "CFG_REQ")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "CFG_REQ irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_CFG_REQ; - } else { - SCSC_TAG_ERR_DEV(PLAT_MIF, &pdev->dev, "Invalid irq res name: %s\n", - irq_res->name); - err = -EINVAL; - goto error_exit; - } - platform->wlbt_irq[irqtag].irq_num = irq_res->start; - platform->wlbt_irq[irqtag].flags = (irq_res->flags & IRQF_TRIGGER_MASK); - atomic_set(&platform->wlbt_irq[irqtag].irq_disabled_cnt, 0); - } - - /* PMU reg map - syscon */ - platform->pmureg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,syscon-phandle"); - if (IS_ERR(platform->pmureg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "syscon regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->pmureg)); - err = -EINVAL; - goto error_exit; - } - - /* Completion event and state used to indicate CFG_REQ IRQ occurred */ - init_completion(&platform->cfg_ack); - platform->boot_state = WLBT_BOOT_IN_RESET; - - /* I3C_APM_PMIC */ - platform->i3c_apm_pmic = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,i3c_apm_pmic-syscon-phandle"); - if (IS_ERR(platform->i3c_apm_pmic)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "i3c_apm_pmic regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->i3c_apm_pmic)); - err = -EINVAL; - goto error_exit; - } - - /* DBUS_BAAW */ - platform->dbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,dbus_baaw-syscon-phandle"); - if (IS_ERR(platform->dbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "dbus_baaw regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->dbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* PBUS_BAAW */ - platform->pbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,pbus_baaw-syscon-phandle"); - if (IS_ERR(platform->pbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "pbus_baaw regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->pbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* WLBT_REMAP */ - platform->wlbt_remap = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,wlbt_remap-syscon-phandle"); - if (IS_ERR(platform->wlbt_remap)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "wlbt_remap regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->wlbt_remap)); - err = -EINVAL; - goto error_exit; - } - - /* BOOT_CFG */ - platform->boot_cfg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,boot_cfg-syscon-phandle"); - if (IS_ERR(platform->boot_cfg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "boot_cfg regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->boot_cfg)); - err = -EINVAL; - goto error_exit; - } - -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER parsing */ - if (!of_property_read_u32(pdev->dev.of_node, "smapper_num_banks", &smapper_banks)) - platform_mif_parse_smapper(platform, platform->dev->of_node, smapper_banks); - -#endif -#ifdef CONFIG_SCSC_QOS - platform_mif_parse_qos(platform, platform->dev->of_node); -#endif - /* Initialize spinlock */ - spin_lock_init(&platform->mif_spinlock); - - return platform_if; - -error_exit: - devm_kfree(&pdev->dev, platform); - return NULL; -} - -void platform_mif_destroy_platform(struct platform_device *pdev, struct scsc_mif_abs *interface) -{ -} - -struct platform_device *platform_mif_get_platform_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->pdev; -} - -struct device *platform_mif_get_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->dev; -} - -/* Preserve MIF registers during suspend. - * If all users of the MIF (AP, mx140, CP, etc) release it, the registers - * will lose their values. Save the useful subset here. - * - * Assumption: the AP will not change the register values between the suspend - * and resume handlers being called! - */ -static void platform_mif_reg_save(struct platform_mif *platform) -{ - platform->mif_preserve.irq_bit_mask = __platform_mif_irq_bit_mask_read(platform); -} - -/* Restore MIF registers that may have been lost during suspend */ -static void platform_mif_reg_restore(struct platform_mif *platform) -{ - __platform_mif_irq_bit_mask_write(platform, platform->mif_preserve.irq_bit_mask); -} - -int platform_mif_suspend(struct scsc_mif_abs *interface) -{ - int r = 0; - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (platform->suspend_handler) - r = platform->suspend_handler(interface, platform->suspendresume_data); - - /* Save the MIF registers. - * This must be done last as the suspend_handler may use the MIF - */ - platform_mif_reg_save(platform); - - return r; -} - -void platform_mif_resume(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - s32 ret; - - /* Restore the MIF registers. - * This must be done first as the resume_handler may use the MIF. - */ - platform_mif_reg_restore(platform); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clear WLBT_ACTIVE_CLR flag\n"); - /* Clear WLBT_ACTIVE_CLR flag in WLBT_CTRL_NS */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, WLBT_ACTIVE_CLR, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret); - } - - if (platform->resume_handler) - platform->resume_handler(interface, platform->suspendresume_data); -} - -/* Temporary workaround to power up slave PMIC LDOs before FW APM/WLBT signalling - * is complete - */ -static void power_supplies_on(struct platform_mif *platform) -{ - struct i2c_client i2c; - - /* HACK: Note only addr field is needed by s2mpu11_write_reg() */ - i2c.addr = 0x1; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT LDOs on (PMIC i2c_addr = 0x%x)\n", i2c.addr); - /* SLAVE PMIC - * adb shell "echo 0x3C > sys/class/pmic/s2mpu12/s2mpu12_read" - * adb shell "echo 0x3C 0xE0 > sys/class/pmic/s2mpu12/s2mpu12_write" - * adb shell "echo 0x3D > /sys/class/pmic/s2mpu12/s2mpu12_read" - * adb shell "echo 0x3D 0xE0 > /sys/class/pmic/s2mpu12/s2mpu12_write" - * adb shell "echo 0x3E > /sys/class/pmic/s2mpu12/s2mpu12_read" - * adb shell "echo 0x3E 0xEC > /sys/class/pmic/s2mpu12/s2mpu12_write" - * adb shell "echo 0x40 > /sys/class/pmic/s2mpu12/s2mpu12_read" - * adb shell "echo 0x40 0xFC > /sys/class/pmic/s2mpu12/s2mpu12_write" - */ - - s2mpu12_write_reg(&i2c, 0x3C, 0xE0); /* LDO 18 */ - s2mpu12_write_reg(&i2c, 0x3D, 0xE0); /* LDO 19 */ - s2mpu12_write_reg(&i2c, 0x3E, 0xEC); /* LDO 20 */ - s2mpu12_write_reg(&i2c, 0x40, 0xFC); /* LDO 22 */ -} diff --git a/drivers/misc/samsung/scsc/platform_mif_9610.c b/drivers/misc/samsung/scsc/platform_mif_9610.c deleted file mode 100644 index ff37b6706222..000000000000 --- a/drivers/misc/samsung/scsc/platform_mif_9610.c +++ /dev/null @@ -1,1956 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Implements interface */ - -#include "platform_mif.h" - -/* Interfaces it Uses */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_OF -#include -#include -#include -#endif -#include -#include -#include -#include -#include "mif_reg_S5E9610.h" -#include "platform_mif_module.h" -#ifdef CONFIG_ARCH_EXYNOS -#include -#endif - -#ifdef CONFIG_SCSC_SMAPPER -#include -#include "mif_reg_smapper.h" -#endif -#ifdef CONFIG_SCSC_QOS -#include -#endif - -#if !defined(CONFIG_SOC_EXYNOS9610) -#error Target processor CONFIG_SOC_EXYNOS9610 not selected -#endif - -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif -/* Time to wait for CFG_REQ IRQ on 9610 */ -#define WLBT_BOOT_TIMEOUT (HZ) - -#ifdef CONFIG_OF_RESERVED_MEM -#include -#endif -static unsigned long sharedmem_base; -static size_t sharedmem_size; - -#ifdef CONFIG_SCSC_CHV_SUPPORT -static bool chv_disable_irq; -module_param(chv_disable_irq, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(chv_disable_irq, "Do not register for irq"); -#endif - -static bool enable_platform_mif_arm_reset = true; -module_param(enable_platform_mif_arm_reset, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_platform_mif_arm_reset, "Enables WIFIBT ARM cores reset"); - -#ifdef CONFIG_SCSC_QOS -struct qos_table { - unsigned int freq_mif; - unsigned int freq_int; - unsigned int freq_cl0; - unsigned int freq_cl1; -}; -#endif - -struct platform_mif { - struct scsc_mif_abs interface; - struct scsc_mbox_s *mbox; - struct platform_device *pdev; - - struct device *dev; - - struct { - int irq_num; - int flags; - atomic_t irq_disabled_cnt; - } wlbt_irq[PLATFORM_MIF_NUM_IRQS]; - - /* MIF registers preserved during suspend */ - struct { - u32 irq_bit_mask; - } mif_preserve; - - /* register MBOX memory space */ - size_t reg_start; - size_t reg_size; - void __iomem *base; - - /* register CMU memory space */ - struct regmap *cmu_base; - - void __iomem *con0_base; - - /* pmu syscon regmap */ - struct regmap *pmureg; -#if defined(CONFIG_SOC_EXYNOS9610) - struct regmap *baaw_p_wlbt; - struct regmap *dbus_baaw; - struct regmap *pbus_baaw; - struct regmap *wlbt_remap; - struct regmap *boot_cfg; - - /* Signalled when CFG_REQ IRQ handled */ - struct completion cfg_ack; - - /* State of CFG_REQ handler */ - enum wlbt_boot_state { - WLBT_BOOT_IN_RESET = 0, - WLBT_BOOT_WAIT_CFG_REQ, - WLBT_BOOT_CFG_DONE, - WLBT_BOOT_CFG_ERROR - } boot_state; - -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER */ - void __iomem *smapper_base; - u8 smapper_banks; - struct { - u8 bank; - u32 ws; - bool large; - struct scsc_mif_smapper_info bank_info; - } *smapper; -#endif - /* Shared memory space - reserved memory */ - unsigned long mem_start; - size_t mem_size; - void __iomem *mem; - - /* Callback function and dev pointer mif_intr manager handler */ - void (*r4_handler)(int irq, void *data); - void *irq_dev; - /* spinlock to serialize driver access */ - spinlock_t mif_spinlock; - void (*reset_request_handler)(int irq, void *data); - void *irq_reset_request_dev; - -#ifdef CONFIG_SCSC_QOS - /* QoS table */ - struct qos_table *qos; - bool qos_enabled; -#endif - /* Suspend/resume handlers */ - int (*suspend_handler)(struct scsc_mif_abs *abs, void *data); - void (*resume_handler)(struct scsc_mif_abs *abs, void *data); - void *suspendresume_data; -}; - -extern int mx140_log_dump(void); - -#define platform_mif_from_mif_abs(MIF_ABS_PTR) container_of(MIF_ABS_PTR, struct platform_mif, interface) - -inline void platform_mif_reg_write(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->base + offset); -} - -inline u32 platform_mif_reg_read(struct platform_mif *platform, u16 offset) -{ - return readl(platform->base + offset); -} - -#ifdef CONFIG_SCSC_SMAPPER -inline void platform_mif_reg_write_smapper(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->smapper_base + offset); -} - -inline u32 platform_mif_reg_read_smapper(struct platform_mif *platform, u16 offset) -{ - return readl(platform->smapper_base + offset); -} - -#define PLATFORM_MIF_SHIFT_SMAPPER_ADDR 11 /* From 36 bits addres to 25 bits */ -#define PLATFORM_MIF_SHIFT_SMAPPER_END 4 /* End address aligment */ - -/* Platform is responsible to give the phys mapping of the SMAPPER maps */ -static int platform_mif_smapper_get_mapping(struct scsc_mif_abs *interface, u8 *phy_map, u16 *align) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Mapping %d banks\n", platform->smapper_banks); - - if (!platform->smapper_banks) - return -EINVAL; - - for (i = 0; i < platform->smapper_banks; i++) { - if (platform->smapper[i].large) - phy_map[i] = SCSC_MIF_ABS_LARGE_BANK; - else - phy_map[i] = SCSC_MIF_ABS_SMALL_BANK; - } - - if (align) - *align = 1 << PLATFORM_MIF_SHIFT_SMAPPER_ADDR; - - return 0; -} - -static int platform_mif_smapper_get_bank_info(struct scsc_mif_abs *interface, u8 bank, struct scsc_mif_smapper_info *bank_info) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper_banks) - return -EINVAL; - - bank_info->num_entries = platform->smapper[bank].bank_info.num_entries; - bank_info->mem_range_bytes = platform->smapper[bank].bank_info.mem_range_bytes; - - return 0; -} - -static u8 platform_mif_smapper_granularity_to_bits(u32 granularity) -{ - if (granularity <= 2 * 1024) - return 0; - if (granularity <= 4 * 1024) - return 1; - if (granularity <= 8 * 1024) - return 2; - if (granularity <= 16 * 1024) - return 3; - if (granularity <= 32 * 1024) - return 4; - if (granularity <= 64 * 1024) - return 5; - if (granularity <= 128 * 1024) - return 6; - return 7; -} - -static u32 platform_mif_smapper_get_bank_base_address(struct scsc_mif_abs *interface, u8 bank) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper) - return 0; - - return platform->smapper[bank].ws; -} - -/* Configure smapper according the memory map and range */ -static void platform_mif_smapper_configure(struct scsc_mif_abs *interface, u32 granularity) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u8 gran; - u8 nb = platform->smapper_banks; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Configure SMAPPER with granularity %d\n", granularity); - - gran = platform_mif_smapper_granularity_to_bits(granularity); - - platform_mif_reg_write_smapper(platform, SMAPPER_QCH_DISABLE, 1); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AR, 0); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AW, 0); - /* Program SMAPPER memmap */ - for (i = 0; i < nb; i++) { - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(i), 0); - /* Set START_ADDR */ - platform_mif_reg_write_smapper(platform, START_ADDR(i), platform->smapper[i].ws); - /* Set ADDR_GRANULARITY - FIXED AT 4KB */ - platform_mif_reg_write_smapper(platform, ADDR_GRANULARITY(i), gran); - /* WLAN_ADDR_MAP operation is started */ - } - /* Set access window control (MSB 32bits Start/End address) */ - /* Remapped address should be ranged from AW_START_ADDR to AW_EN_ADDR */ - platform_mif_reg_write_smapper(platform, AW_START_ADDR, 0); - platform_mif_reg_write_smapper(platform, AW_END_ADDR, dma_get_mask(platform->dev) >> PLATFORM_MIF_SHIFT_SMAPPER_END); - smp_mb(); -} - -/* Caller is responsible of validating the phys address (alignment) */ -static int platform_mif_smapper_write_sram(struct scsc_mif_abs *interface, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u32 rb; - - if (!platform->smapper_banks) - return -EINVAL; - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "SMAPPER not enabled\n"); - return -EINVAL; - } - - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 0); - /* Write mapping table to SRAM. Each entry consists of 25 bits MSB address to remap */ - for (i = 0; i < num_entries; i++) { - if (!addr[i]) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ADDR IS NULL at bank %d entry %d/%d\n", bank, first_entry + i, num_entries); - return -EINVAL; - } - /* Set SRAM_WRITE_CTRL to 1'b1*/ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 1); - platform_mif_reg_write_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i), addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - /* check incorrect writings */ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 0); - rb = platform_mif_reg_read_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i)); - if (rb != addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "incorrect mapping detected rb 0x%x, addr 0x%x\n", rb, (u32)addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - return -EFAULT; - } - } - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 1); - smp_mb(); - return 0; -} - -static int platform_mif_parse_smapper(struct platform_mif *platform, struct device_node *np, u8 num_banks) -{ - /* SMAPPER parsing */ - struct device_node *np_banks; - char node_name[50]; - u32 val[2]; - u8 i; - u32 bank = 0, ws = 0, wsz = 0, ent = 0, large = 0; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "banks found: %d szof %zu\n", num_banks, sizeof(*platform->smapper)); - - platform->smapper = kmalloc_array(num_banks, sizeof(*platform->smapper), GFP_KERNEL); - - if (!platform->smapper) - return -ENOMEM; - - for (i = 0; i < num_banks; i++) { - snprintf(node_name, sizeof(node_name), "smapper_bank_%d", i); - np_banks = of_find_node_by_name(np, node_name); - if (!np_banks) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "%s: could not find smapper_bank\n", - node_name); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - of_property_read_u32(np_banks, "bank_num", &bank); - of_property_read_u32(np_banks, "fw_window_start", &ws); - of_property_read_u32(np_banks, "fw_window_size", &wsz); - of_property_read_u32(np_banks, "num_entries", &ent); - of_property_read_u32(np_banks, "is_large", &large); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "bank %d fw_w_start 0x%x fw_w_sz 0x%x entries %d is_large %d\n", - bank, ws, wsz, ent, large); - - platform->smapper[i].bank = (u8)bank; - platform->smapper[i].ws = ws; - platform->smapper[i].large = (bool)large; - platform->smapper[i].bank_info.num_entries = ent; - platform->smapper[i].bank_info.mem_range_bytes = wsz; - } - - /* Update the number of banks before returning */ - platform->smapper_banks = num_banks; - - of_property_read_u32_array(np, "smapper_reg", val, 2); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "smapper reg address 0x%x size 0x%x\n", val[0], val[1]); - platform->smapper_base = - devm_ioremap_nocache(platform->dev, val[0], val[1]); - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping smapper register region\n"); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - - return 0; -} -#endif -#ifdef CONFIG_SCSC_QOS -static int platform_mif_parse_qos(struct platform_mif *platform, struct device_node *np) -{ - int len, i; - - platform->qos_enabled = false; - - len = of_property_count_u32_elems(np, "qos_table"); - if (!(len == 12)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "No qos table for wlbt, or incorrect size\n"); - return -ENOENT; - } - - platform->qos = devm_kzalloc(platform->dev, sizeof(struct qos_table) * len / 4, GFP_KERNEL); - if (!platform->qos) - return -ENOMEM; - - of_property_read_u32_array(np, "qos_table", (unsigned int *)platform->qos, len); - - for (i = 0; i < len / 4; i++) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "QoS Table[%d] mif : %u int : %u cl0 : %u cl1: %u\n", i, - platform->qos[i].freq_mif, - platform->qos[i].freq_int, - platform->qos[i].freq_cl0, - platform->qos[i].freq_cl1); - } - - platform->qos_enabled = true; - return 0; -} - -struct qos_table platform_mif_pm_qos_get_table(struct platform_mif *platform, enum scsc_qos_config config) -{ - struct qos_table table; - - switch (config) { - case SCSC_QOS_MIN: - table.freq_mif = platform->qos[0].freq_mif; - table.freq_int = platform->qos[0].freq_int; - table.freq_cl0 = platform->qos[0].freq_cl0; - table.freq_cl1 = platform->qos[0].freq_cl1; - break; - - case SCSC_QOS_MED: - table.freq_mif = platform->qos[1].freq_mif; - table.freq_int = platform->qos[1].freq_int; - table.freq_cl0 = platform->qos[1].freq_cl0; - table.freq_cl1 = platform->qos[1].freq_cl1; - break; - - case SCSC_QOS_MAX: - table.freq_mif = platform->qos[2].freq_mif; - table.freq_int = platform->qos[2].freq_int; - table.freq_cl0 = platform->qos[2].freq_cl0; - table.freq_cl1 = platform->qos[2].freq_cl1; - break; - - default: - table.freq_mif = 0; - table.freq_int = 0; - table.freq_cl0 = 0; - table.freq_cl1 = 0; - } - - return table; -} - -static int platform_mif_pm_qos_add_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS add request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_add_request(&qos_req->pm_qos_req_mif, PM_QOS_BUS_THROUGHPUT, table.freq_mif); - pm_qos_add_request(&qos_req->pm_qos_req_int, PM_QOS_DEVICE_THROUGHPUT, table.freq_int); - pm_qos_add_request(&qos_req->pm_qos_req_cl0, PM_QOS_CLUSTER0_FREQ_MIN, table.freq_cl0); - pm_qos_add_request(&qos_req->pm_qos_req_cl1, PM_QOS_CLUSTER1_FREQ_MIN, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_update_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS update request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_update_request(&qos_req->pm_qos_req_mif, table.freq_mif); - pm_qos_update_request(&qos_req->pm_qos_req_int, table.freq_int); - pm_qos_update_request(&qos_req->pm_qos_req_cl0, table.freq_cl0); - pm_qos_update_request(&qos_req->pm_qos_req_cl1, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_remove_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform) - return -ENODEV; - - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS remove request\n"); - pm_qos_remove_request(&qos_req->pm_qos_req_mif); - pm_qos_remove_request(&qos_req->pm_qos_req_int); - pm_qos_remove_request(&qos_req->pm_qos_req_cl0); - pm_qos_remove_request(&qos_req->pm_qos_req_cl1); - - return 0; -} -#endif - -static void platform_mif_irq_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT handler not registered\n"); -} - -static void platform_mif_irq_reset_request_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT reset_request handler not registered\n"); -} - -irqreturn_t platform_mif_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "INT %pS\n", platform->r4_handler); - if (platform->r4_handler != platform_mif_irq_default_handler) - platform->r4_handler(irq, platform->irq_dev); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MIF Interrupt Handler not registered\n"); - - return IRQ_HANDLED; -} - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ -irqreturn_t platform_alive_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - - return IRQ_HANDLED; -} -#endif - -irqreturn_t platform_wdog_isr(int irq, void *data) -{ - int ret = 0; - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - if (platform->reset_request_handler != platform_mif_irq_reset_request_default_handler) { - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - platform->reset_request_handler(irq, platform->irq_reset_request_dev); - } else { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG Interrupt reset_request_handler not registered\n"); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Disabling unhandled WDOG IRQ.\n"); - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_inc(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt); - } -#ifdef CONFIG_SOC_EXYNOS9610 - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_RESET_REQ_CLR, WLBT_RESET_REQ_CLR); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clearing WLBT_RESET_REQ\n"); - if (ret < 0) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_RESET_REQ_CLR]: %d\n", ret); -#endif - return IRQ_HANDLED; -} - -#ifdef CONFIG_SOC_EXYNOS9610 -/* - * Attached array contains the replacement PMU boot code which should - * be programmed using the CBUS during the config phase. - */ -uint32_t ka_patch[] = { - /* Low temp fix 28/1 - * Maxwell142 PMU+PROC combined boot ROM - * IP Version: 0xA3 - * Major Version: 0xF, Minor Version: 0xF - * PMU ROM version: 0x4 - * PROC ROM version: 0x0 - */ - 0x90750002, - 0x11a4c218, - 0x75671191, - 0x9075e090, - 0x54b3e5e7, - 0x30f76001, - 0xb14315a2, - 0xb4b2e503, - 0xb153fb03, - 0xa90185fc, - 0xacf50774, - 0x75fdadb5, - 0xb47508a0, - 0x54b3e501, - 0x75fa7001, - 0x907500b4, - 0x78cb8018, - 0x80837982, - 0x07a075c5, - 0xb0783779, - 0xb40754e6, - 0x0b800207, - 0xc404f6d9, - 0xaf7590f5, - 0x75038000, - 0x53229090, - 0xce53eff7, - 0xd90479fe, - 0xfdce53fe, - 0xfed90c79, - 0x75fbce53, - 0x91530b92, - 0xf7ce53fd, - 0x5308f943, - 0xf922fef9, - 0xfbd8fed9, - 0x019e7522, - 0x75cfc175, - 0xc375a4c2, - 0x47c4754a, - 0x75a4c575, - 0xc7756dc6, - 0x03d27540, - 0x7510d375, - 0xca7500c9, - 0x00cb75d0, - 0x7500cc75, - 0x9b75009a, - 0x009c75c0, - 0x78009d75, - 0x12827402, - 0xc6438b80, - 0x74097802, - 0x8b8012e7, - 0x75d09075, - 0x9e750291, - 0x01a97502, - 0x00000022, -}; - -extern bool reset_failed; - -irqreturn_t platform_cfg_req_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - const u64 EXYNOS_WLBT = 0x1; - u64 ret64 = 0; - s32 ret = 0; - unsigned int ka_addr = 0x1000; - uint32_t *ka_patch_addr = ka_patch; - u32 id; - -#define CHECK(x) do { \ - int retval = (x); \ - if (retval < 0) \ - goto cfg_error; \ -} while (0) - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "disable_irq\n"); - - /* mask the irq */ - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - /* Was the CFG_REQ irq received from WLBT before we expected it? - * Typically this indicates an issue returning WLBT HW to reset. - */ - if (platform->boot_state != WLBT_BOOT_WAIT_CFG_REQ) { - u32 val; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Spurious CFG_REQ IRQ from WLBT!\n"); - - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_NS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_S 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - reset_failed = true; /* prevent further interaction with HW */ - - return IRQ_HANDLED; - } - - /* CBUS should be ready before we get CFG_REQ, but we suspect - * CBUS is not ready yet. add some delay to see if that helps - */ - udelay(100); - - /* Set TZPC to non-secure mode */ - ret64 = exynos_smc(SMC_CMD_CONN_IF, (EXYNOS_WLBT << 32) | EXYNOS_SET_CONN_TZPC, 0, 0); - if (ret64) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to set TZPC to non-secure mode: %llu\n", ret64); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SMC_CMD_CONN_IF run successfully : %llu\n", ret64); - - /* WLBT_REMAP */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP begin\n"); - CHECK(regmap_write(platform->wlbt_remap, 0x0, WLBT_DBUS_BAAW_0_START >> 12)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP end\n"); - - /* CHIP_VERSION_ID - overload with EMA settings */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "CHIP_VERSION_ID begin\n"); - regmap_read(platform->wlbt_remap, 0x10, &id); - id &= ~CHIP_VERSION_ID_EMA_MASK; - id |= CHIP_VERSION_ID_EMA_VALUE; - CHECK(regmap_write(platform->wlbt_remap, 0x10, id)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "CHIP_VERSION_ID 0x%x end\n", id); - - /* DBUS_BAAW regions */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW begin\n"); - CHECK(regmap_write(platform->dbus_baaw, 0x0, WLBT_DBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x4, WLBT_DBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x8, platform->mem_start >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW end\n"); - - /* PBUS_BAAW regions */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW begin\n"); - CHECK(regmap_write(platform->pbus_baaw, 0x0, WLBT_PBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4, WLBT_PBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x8, WLBT_PBUS_MBOX_CP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x10, WLBT_PBUS_BAAW_1_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x14, WLBT_PBUS_BAAW_1_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x18, WLBT_PBUS_MBOX_SHUB2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x1C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x20, WLBT_PBUS_BAAW_2_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x24, WLBT_PBUS_BAAW_2_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x28, WLBT_PBUS_USI_CMG00_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x2C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x30, WLBT_PBUS_BAAW_3_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x34, WLBT_PBUS_BAAW_3_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x38, WLBT_PBUS_SYSREG_CMGP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x3C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x40, WLBT_PBUS_BAAW_4_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x44, WLBT_PBUS_BAAW_4_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x48, WLBT_PBUS_GPIO_CMGP_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x50, WLBT_PBUS_BAAW_5_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x54, WLBT_PBUS_BAAW_5_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x58, WLBT_PBUS_SHUB_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x5C, WLBT_BAAW_ACCESS_CTRL)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW end\n"); - - /* PMU boot bug workaround */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT begin\n"); - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x1)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT done\n"); - - while (ka_patch_addr < (ka_patch + ARRAY_SIZE(ka_patch))) { - CHECK(regmap_write(platform->boot_cfg, ka_addr, *ka_patch_addr)); - ka_addr += sizeof(ka_patch[0]); - ka_patch_addr++; - } - - /* Notify PMU of configuration done */ - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x0)); - - /* BOOT_CFG_ACK */ - CHECK(regmap_write(platform->boot_cfg, 0x4, 0x1)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_CFG_ACK done\n"); - - /* Delay to allow HW to clear CFG_REQ and hence de-assert IRQ, which - * it does in response to CFG_ACK - */ - udelay(100); - - /* Release ownership of MASK_PWR_REQ */ - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - MASK_PWR_REQ, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to clear WLBT_CTRL_NS[MASK_PWR_REQ]: %d\n", ret); - goto cfg_error; - } - - /* Mark as CFQ_REQ handled, so boot may continue */ - platform->boot_state = WLBT_BOOT_CFG_DONE; - - /* Signal triggering function that the IRQ arrived and CFG was done */ - complete(&platform->cfg_ack); - - /* Re-enable IRQ here to allow spurious interrupt to be tracked */ - enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - return IRQ_HANDLED; -cfg_error: - platform->boot_state = WLBT_BOOT_CFG_ERROR; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ERROR: WLBT Config failed. WLBT will not work\n"); - complete(&platform->cfg_ack); - return IRQ_HANDLED; -} -#endif - -static void platform_mif_unregister_irq(struct platform_mif *platform) -{ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering IRQs\n"); - - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform); - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform); - /* Reset irq_disabled_cnt for WDOG IRQ since the IRQ itself is here unregistered and disabled */ - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* if ALIVE irq is required */ - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform); -#endif -#ifdef CONFIG_SOC_EXYNOS9610 - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform); -#endif -} - -static int platform_mif_register_irq(struct platform_mif *platform) -{ - int err; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering IRQs\n"); - - /* Register MBOX irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering MBOX irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform->wlbt_irq[PLATFORM_MIF_MBOX].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform_mif_isr, - platform->wlbt_irq[PLATFORM_MIF_MBOX].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register MBOX handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - - /* Register WDOG irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering WDOG irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform->wlbt_irq[PLATFORM_MIF_WDOG].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform_wdog_isr, - platform->wlbt_irq[PLATFORM_MIF_WDOG].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register WDOG handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* Register ALIVE irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering ALIVE irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform_alive_isr, - platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags, DRV_NAME, platform); - if (IS_ERR_VALUE(err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register ALIVE handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } -#endif - -#ifdef CONFIG_SOC_EXYNOS9610 - /* Mark as WLBT in reset before enabling IRQ to guard against spurious IRQ */ - platform->boot_state = WLBT_BOOT_IN_RESET; - smp_wmb(); /* commit before irq */ - - /* Register WB2AP_CFG_REQ irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering CFG_REQ irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform_cfg_req_isr, - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register CFG_REQ handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } -#endif - return 0; -} - -static void platform_mif_destroy(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - platform_mif_unregister_irq(platform); -} - -static char *platform_mif_get_uid(struct scsc_mif_abs *interface) -{ - /* Avoid unused parameter error */ - (void)interface; - return "0"; -} - -/* WLBT Power domain */ -static int platform_mif_power(struct scsc_mif_abs *interface, bool power) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val = 0; - s32 ret = 0; -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "power %d\n", power); - - if (power) - val = MASK_PWR_REQ; - - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - MASK_PWR_REQ, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[MASK_PWR_REQ]: %d\n", ret); - return ret; - } -#endif - return 0; -} - -/* WLBT RESET */ -static int platform_mif_hold_reset(struct scsc_mif_abs *interface, bool reset) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val = 0; - s32 ret = 0; -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "reset %d\n", reset); - if (reset) - val = WLBT_RESET_SET; - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_RESET_SET, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[WLBT_RESET_SET]: %d\n", ret); - return ret; - } -#endif - return 0; -} - -/* WLBT START */ -static int platform_mif_start(struct scsc_mif_abs *interface, bool start) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val = 0; - s32 ret = 0; - -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "start %d\n", start); - if (start) - val = WLBT_START; - - /* See sequence in 9.6.6 */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S, - WLBT_START, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret); - return ret; - } - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "update WIFI_CTRL_S[WIFI_START]: %d\n", ret); - - /* At this point WLBT should assert the CFG_REQ IRQ, so wait for it */ - if (start && - wait_for_completion_timeout(&platform->cfg_ack, WLBT_BOOT_TIMEOUT) == 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Timeout waiting for CFG_REQ IRQ\n"); - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - return -ETIMEDOUT; - } - /* only continue if CFG_REQ IRQ configured WLBT/PMU correctly */ - if (platform->boot_state == WLBT_BOOT_CFG_ERROR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "CFG_REQ failed to configure WLBT.\n"); - return -EIO; - } -#endif - return 0; -} - -static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface) -{ - int ret = 0; - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - -#ifdef CONFIG_SOC_EXYNOS9610 - /* We're now ready for the IRQ */ - platform->boot_state = WLBT_BOOT_WAIT_CFG_REQ; - smp_wmb(); /* commit before irq */ -#endif - ret = platform_mif_power(interface, true); - if (ret) - return ret; - ret = platform_mif_hold_reset(interface, false); - if (ret) - return ret; - ret = platform_mif_start(interface, true); - if (ret) - return ret; - - return ret; -} - -static int platform_mif_pmu_reset(struct scsc_mif_abs *interface, u8 rst_case) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long timeout; - int ret; - u32 val; - - if (rst_case == 0 || rst_case > 2) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Incorrect pmu reset case %d\n", rst_case); - return -EIO; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "rst_case %d\n", rst_case); - - /* Revert power control ownership to AP, as WLBT is going down (S9.6.6). */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - MASK_PWR_REQ, MASK_PWR_REQ); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_NS[MASK_PWR_REQ]: %d\n", ret); - return ret; - } - - /* reset sequence as per excite implementation for Leman */ - ret = regmap_update_bits(platform->pmureg, CENTRAL_SEQ_WLBT_CONFIGURATION, - SYS_PWR_CFG_16, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update CENTRAL_SEQ_WLBT_CONFIGURATION %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, RESET_AHEAD_WLBT_SYS_PWR_REG, - SYS_PWR_CFG_2, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update RESET_AHEAD_WLBT_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, CLEANY_BUS_WLBT_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update CLEANY_BUS_WLBT_SYS_PWR_REG%d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, LOGIC_RESET_WLBT_SYS_PWR_REG, - SYS_PWR_CFG_2, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update LOGIC_RESET_WLBT_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, TCXO_GATE_WLBT_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update TCXO_GATE_WLBT_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, WLBT_DISABLE_ISO_SYS_PWR_REG, - SYS_PWR_CFG, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_DISABLE_ISO_SYS_PWR_REG %d\n", ret); - return ret; - } - - ret = regmap_update_bits(platform->pmureg, WLBT_RESET_ISO_SYS_PWR_REG, - SYS_PWR_CFG, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_RESET_ISO_SYS_PWR_REG %d\n", ret); - return ret; - } - - /* rst_case is always 2 on 9610 */ - ret = platform_mif_hold_reset(interface, true); - - if (ret) - return ret; - - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - val &= STATES; - val >>= 16; - if (val == 0x80) { - /* OK. Switch CTRL_NS[MASK_PWR_REQ] ownership to FW following - * reset. WLBT PWR_REQ is cleared when it's put in reset. - * The SW PWR_REQ remains asserted, but as ownership is now FW, - * it'll be ignored. This leaves it as we found it. - */ - platform_mif_power(interface, false); - - return 0; /* OK - return */ - } - } while (time_before(jiffies, timeout)); - - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Timeout waiting for CENTRAL_SEQ_WLBT_STATUS SM status\n"); - regmap_read(platform->pmureg, CENTRAL_SEQ_WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "CENTRAL_SEQ_WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - return -ETIME; -} - -/* reset=0 - release from reset */ -/* reset=1 - hold reset */ -static int platform_mif_reset(struct scsc_mif_abs *interface, bool reset) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 ret = 0; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (enable_platform_mif_arm_reset || !reset) { - if (!reset) { /* Release from reset */ -#ifdef CONFIG_ARCH_EXYNOS - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SOC_VERSION: product_id 0x%x, rev 0x%x\n", - exynos_soc_info.product_id, exynos_soc_info.revision); -#endif - ret = platform_mif_pmu_reset_release(interface); - } else { - /* Put back into reset */ - ret = platform_mif_pmu_reset(interface, 2); - } - } else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Not resetting ARM Cores - enable_platform_mif_arm_reset: %d\n", - enable_platform_mif_arm_reset); - return ret; -} - -static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size) -{ - int i; - struct page **pages; - void *vmem; - - size = PAGE_ALIGN(size); - - pages = kmalloc((size >> PAGE_SHIFT) * sizeof(*pages), GFP_KERNEL); - if (!pages) - return NULL; - - /* Map NORMAL_NC pages with kernel virtual space */ - for (i = 0; i < (size >> PAGE_SHIFT); i++) { - pages[i] = phys_to_page(phys_addr); - phys_addr += PAGE_SIZE; - } - - vmem = vmap(pages, size >> PAGE_SHIFT, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); - - kfree(pages); - return (void __iomem *)vmem; -} - -static void platform_mif_unmap_region(void *vmem) -{ - vunmap(vmem); -} - -static void *platform_mif_map(struct scsc_mif_abs *interface, size_t *allocated) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - if (allocated) - *allocated = 0; - - platform->mem = - platform_mif_map_region(platform->mem_start, platform->mem_size); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Error remaping shared memory\n"); - return NULL; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Map: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - - /* Initialise MIF registers with documented defaults */ - /* MBOXes */ - for (i = 0; i < NUM_MBOX_PLAT; i++) - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(ISSR(i)), 0x00000000); - - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); - -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_disable_irq == true) { - if (allocated) - *allocated = platform->mem_size; - return platform->mem; - } -#endif - /* register interrupts */ - if (platform_mif_register_irq(platform)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - return NULL; - } - - if (allocated) - *allocated = platform->mem_size; - /* Set the CR4 base address in Mailbox??*/ - return platform->mem; -} - -/* HERE: Not sure why mem is passed in - its stored in platform - as it should be */ -static void platform_mif_unmap(struct scsc_mif_abs *interface, void *mem) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - /* Avoid unused parameter error */ - (void)mem; - - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); - -#ifdef CONFIG_SCSC_CHV_SUPPORT - /* Restore PIO changed by Maxwell subsystem */ - if (chv_disable_irq == false) - /* Unregister IRQs */ - platform_mif_unregister_irq(platform); -#else - platform_mif_unregister_irq(platform); -#endif - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - platform->mem = NULL; -} - -static u32 platform_mif_irq_bit_mask_status_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INTMR0: 0x%x\n", val); - return val; -} - -static u32 platform_mif_irq_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - /* Function has to return the interrupts that are enabled *AND* not masked */ - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INT-INTMSR0: 0x%x\n", val); - - return val; -} - -static void platform_mif_irq_bit_set(struct scsc_mif_abs *interface, int bit_num, enum scsc_mif_abs_target target) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 reg; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - -#ifdef CONFIG_SOC_EXYNOS9610 - reg = INTGR1; - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(reg), (1 << bit_num)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTGR1: bit %d on target %d\n", bit_num, target); -#endif -} - -static void platform_mif_irq_bit_clear(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - /* WRITE : 1 = Clears Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), ((1 << bit_num) << 16)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTCR0: bit %d\n", bit_num); -} - -static void platform_mif_irq_bit_mask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 1 = Mask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val | ((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTMR0: 0x%x bit %d\n", val | (1 << bit_num), bit_num); -} - -static void platform_mif_irq_bit_unmask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 0 = Unmask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val & ~((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "UNMASK Setting INTMR0: 0x%x bit %d\n", val & ~((1 << bit_num) << 16), bit_num); -} - -/* Return the contents of the mask register */ -static u32 __platform_mif_irq_bit_mask_read(struct platform_mif *platform) -{ - u32 val; - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Read INTMR0: 0x%x\n", val); - - return val; -} - -/* Write the mask register, destroying previous contents */ -static void __platform_mif_irq_bit_mask_write(struct platform_mif *platform, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Write INTMR0: 0x%x\n", val); -} - -static void platform_mif_irq_reg_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif int handler %pS in %p %p\n", handler, platform, interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = handler; - platform->irq_dev = dev; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif int handler %pS\n", interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_reg_reset_request_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif reset_request int handler %pS in %p %p\n", handler, platform, interface); - platform->reset_request_handler = handler; - platform->irq_reset_request_dev = dev; - if (atomic_read(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "Default WDOG handler disabled by spurios IRQ...re-enabling.\n"); - enable_irq(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); - } -} - -static void platform_mif_irq_unreg_reset_request_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "UnRegistering mif reset_request int handler %pS\n", interface); - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; -} - -static void platform_mif_suspend_reg_handler(struct scsc_mif_abs *interface, - int (*suspend)(struct scsc_mif_abs *abs, void *data), - void (*resume)(struct scsc_mif_abs *abs, void *data), - void *data) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = suspend; - platform->resume_handler = resume; - platform->suspendresume_data = data; -} - -static void platform_mif_suspend_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; -} - -static u32 *platform_mif_get_mbox_ptr(struct scsc_mif_abs *interface, u32 mbox_index) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 *addr; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "mbox_index 0x%x\n", mbox_index); - addr = platform->base + MAILBOX_WLBT_REG(ISSR(mbox_index)); - return addr; -} - -static int platform_mif_get_mifram_ref(struct scsc_mif_abs *interface, void *ptr, scsc_mifram_ref *ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return -ENOMEM; - } - - /* Check limits! */ - if (ptr >= (platform->mem + platform->mem_size)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Unable to get pointer reference\n"); - return -ENOMEM; - } - - *ref = (scsc_mifram_ref)((uintptr_t)ptr - (uintptr_t)platform->mem); - - return 0; -} - -static void *platform_mif_get_mifram_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - /* Check limits */ - if (ref >= 0 && ref < platform->mem_size) - return (void *)((uintptr_t)platform->mem + (uintptr_t)ref); - else - return NULL; -} - -static void *platform_mif_get_mifram_phy_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem_start) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - return (void *)((uintptr_t)platform->mem_start + (uintptr_t)ref); -} - -static uintptr_t platform_mif_get_mif_pfn(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - return vmalloc_to_pfn(platform->mem); -} - -static struct device *platform_mif_get_mif_device(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - return platform->dev; -} - -static void platform_mif_irq_clear(void) -{ - /* Implement if required */ -} - -static int platform_mif_read_register(struct scsc_mif_abs *interface, u64 id, u32 *val) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (id == SCSC_REG_READ_WLBT_STAT) { - regmap_read(platform->pmureg, WLBT_STAT, val); - return 0; - } - - return -EIO; -} - -static void platform_mif_dump_register(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR1))); - - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_cleanup(struct scsc_mif_abs *interface) -{ -} - -static void platform_mif_restart(struct scsc_mif_abs *interface) -{ -} - -#ifdef CONFIG_OF_RESERVED_MEM -static int __init platform_mif_wifibt_if_reserved_mem_setup(struct reserved_mem *remem) -{ - SCSC_TAG_DEBUG(PLAT_MIF, "memory reserved: mem_base=%#lx, mem_size=%zd\n", - (unsigned long)remem->base, (size_t)remem->size); - - sharedmem_base = remem->base; - sharedmem_size = remem->size; - return 0; -} -RESERVEDMEM_OF_DECLARE(wifibt_if, "exynos,wifibt_if", platform_mif_wifibt_if_reserved_mem_setup); -#endif - -struct scsc_mif_abs *platform_mif_create(struct platform_device *pdev) -{ - struct scsc_mif_abs *platform_if; - struct platform_mif *platform = - (struct platform_mif *)devm_kzalloc(&pdev->dev, sizeof(struct platform_mif), GFP_KERNEL); - int err = 0; - u8 i = 0; - struct resource *reg_res; - -#ifdef CONFIG_SCSC_SMAPPER - u32 smapper_banks = 0; -#endif - - if (!platform) - return NULL; - - SCSC_TAG_INFO_DEV(PLAT_MIF, &pdev->dev, "Creating MIF platform device\n"); - - platform_if = &platform->interface; - - /* initialise interface structure */ - platform_if->destroy = platform_mif_destroy; - platform_if->get_uid = platform_mif_get_uid; - platform_if->reset = platform_mif_reset; - platform_if->map = platform_mif_map; - platform_if->unmap = platform_mif_unmap; - platform_if->irq_bit_set = platform_mif_irq_bit_set; - platform_if->irq_get = platform_mif_irq_get; - platform_if->irq_bit_mask_status_get = platform_mif_irq_bit_mask_status_get; - platform_if->irq_bit_clear = platform_mif_irq_bit_clear; - platform_if->irq_bit_mask = platform_mif_irq_bit_mask; - platform_if->irq_bit_unmask = platform_mif_irq_bit_unmask; - platform_if->irq_reg_handler = platform_mif_irq_reg_handler; - platform_if->irq_unreg_handler = platform_mif_irq_unreg_handler; - platform_if->irq_reg_reset_request_handler = platform_mif_irq_reg_reset_request_handler; - platform_if->irq_unreg_reset_request_handler = platform_mif_irq_unreg_reset_request_handler; - platform_if->suspend_reg_handler = platform_mif_suspend_reg_handler; - platform_if->suspend_unreg_handler = platform_mif_suspend_unreg_handler; - platform_if->get_mbox_ptr = platform_mif_get_mbox_ptr; - platform_if->get_mifram_ptr = platform_mif_get_mifram_ptr; - platform_if->get_mifram_ref = platform_mif_get_mifram_ref; - platform_if->get_mifram_pfn = platform_mif_get_mif_pfn; - platform_if->get_mifram_phy_ptr = platform_mif_get_mifram_phy_ptr; - platform_if->get_mif_device = platform_mif_get_mif_device; - platform_if->irq_clear = platform_mif_irq_clear; - platform_if->mif_dump_registers = platform_mif_dump_register; - platform_if->mif_read_register = platform_mif_read_register; - platform_if->mif_cleanup = platform_mif_cleanup; - platform_if->mif_restart = platform_mif_restart; -#ifdef CONFIG_SCSC_SMAPPER - platform_if->mif_smapper_get_mapping = platform_mif_smapper_get_mapping; - platform_if->mif_smapper_get_bank_info = platform_mif_smapper_get_bank_info; - platform_if->mif_smapper_write_sram = platform_mif_smapper_write_sram; - platform_if->mif_smapper_configure = platform_mif_smapper_configure; - platform_if->mif_smapper_get_bank_base_address = platform_mif_smapper_get_bank_base_address; -#endif -#ifdef CONFIG_SCSC_QOS - platform_if->mif_pm_qos_add_request = platform_mif_pm_qos_add_request; - platform_if->mif_pm_qos_update_request = platform_mif_pm_qos_update_request; - platform_if->mif_pm_qos_remove_request = platform_mif_pm_qos_remove_request; -#endif - /* Update state */ - platform->pdev = pdev; - platform->dev = &pdev->dev; - - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; - -#ifdef CONFIG_OF_RESERVED_MEM - platform->mem_start = sharedmem_base; - platform->mem_size = sharedmem_size; -#else - /* If CONFIG_OF_RESERVED_MEM is not defined, sharedmem values should be - * parsed from the scsc_wifibt binding - */ - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-base", &sharedmem_base)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_start = sharedmem_base; - - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-size", &sharedmem_size)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_size = sharedmem_size; -#endif -#ifdef CONFIG_SCSC_SMAPPER - platform->smapper = NULL; -#endif - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->mem_start 0x%x platform->mem_size 0x%x\n", - (u32)platform->mem_start, (u32)platform->mem_size); - if (platform->mem_start == 0) - SCSC_TAG_WARNING_DEV(PLAT_MIF, platform->dev, "platform->mem_start is 0"); - - if (platform->mem_size == 0) { - /* We return return if mem_size is 0 as it does not make any sense. - * This may be an indication of an incorrect platform device binding. - */ - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "platform->mem_size is 0"); - err = -EINVAL; - goto error_exit; - } - - /* Memory resource - Phys Address of MAILBOX_WLBT register map */ - reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!reg_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error getting mem resource for MAILBOX_WLBT\n"); - err = -ENOENT; - goto error_exit; - } - - platform->reg_start = reg_res->start; - platform->reg_size = resource_size(reg_res); - - platform->base = - devm_ioremap_nocache(platform->dev, reg_res->start, resource_size(reg_res)); - - if (!platform->base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping register region\n"); - err = -EBUSY; - goto error_exit; - } - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->reg_start %lx size %x base %p\n", - (uintptr_t)platform->reg_start, (u32)platform->reg_size, platform->base); - - /* Get the 4 IRQ resources */ - for (i = 0; i < 4; i++) { - struct resource *irq_res; - int irqtag; - - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!irq_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "No IRQ resource at index %d\n", i); - err = -ENOENT; - goto error_exit; - } - - if (!strcmp(irq_res->name, "MBOX")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MBOX irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_MBOX; - } else if (!strcmp(irq_res->name, "ALIVE")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "ALIVE irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_ALIVE; - } else if (!strcmp(irq_res->name, "WDOG")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_WDOG; - } else if (!strcmp(irq_res->name, "CFG_REQ")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "CFG_REQ irq %d flag 0x%x\n", (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_CFG_REQ; - } else { - SCSC_TAG_ERR_DEV(PLAT_MIF, &pdev->dev, "Invalid irq res name: %s\n", - irq_res->name); - err = -EINVAL; - goto error_exit; - } - platform->wlbt_irq[irqtag].irq_num = irq_res->start; - platform->wlbt_irq[irqtag].flags = (irq_res->flags & IRQF_TRIGGER_MASK); - atomic_set(&platform->wlbt_irq[irqtag].irq_disabled_cnt, 0); - } - - /* PMU reg map - syscon */ - platform->pmureg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,syscon-phandle"); - if (IS_ERR(platform->pmureg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "syscon regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->pmureg)); - err = -EINVAL; - goto error_exit; - } - -#ifdef CONFIG_SOC_EXYNOS9610 - /* Completion event and state used to indicate CFG_REQ IRQ occurred */ - init_completion(&platform->cfg_ack); - platform->boot_state = WLBT_BOOT_IN_RESET; - - /* BAAW_P_WLBT */ - platform->baaw_p_wlbt = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,baaw_p_wlbt-syscon-phandle"); - if (IS_ERR(platform->baaw_p_wlbt)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "baaw_p_wlbt regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->baaw_p_wlbt)); - err = -EINVAL; - goto error_exit; - } - - /* DBUS_BAAW */ - platform->dbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,dbus_baaw-syscon-phandle"); - if (IS_ERR(platform->dbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "dbus_baaw regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->dbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* PBUS_BAAW */ - platform->pbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,pbus_baaw-syscon-phandle"); - if (IS_ERR(platform->pbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "pbus_baaw regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->pbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* WLBT_REMAP */ - platform->wlbt_remap = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,wlbt_remap-syscon-phandle"); - if (IS_ERR(platform->wlbt_remap)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "wlbt_remap regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->wlbt_remap)); - err = -EINVAL; - goto error_exit; - } - - /* BOOT_CFG */ - platform->boot_cfg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,boot_cfg-syscon-phandle"); - if (IS_ERR(platform->boot_cfg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "boot_cfg regmap lookup failed. Aborting. %ld\n", PTR_ERR(platform->boot_cfg)); - err = -EINVAL; - goto error_exit; - } -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER parsing */ - if (!of_property_read_u32(pdev->dev.of_node, "smapper_num_banks", &smapper_banks)) - platform_mif_parse_smapper(platform, platform->dev->of_node, smapper_banks); - -#endif -#ifdef CONFIG_SCSC_QOS - platform_mif_parse_qos(platform, platform->dev->of_node); -#endif - /* Initialize spinlock */ - spin_lock_init(&platform->mif_spinlock); - - return platform_if; - -error_exit: - devm_kfree(&pdev->dev, platform); - return NULL; -} - -void platform_mif_destroy_platform(struct platform_device *pdev, struct scsc_mif_abs *interface) -{ -} - -struct platform_device *platform_mif_get_platform_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->pdev; -} - -struct device *platform_mif_get_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->dev; -} - -/* Preserve MIF registers during suspend. - * If all users of the MIF (AP, mx140, CP, etc) release it, the registers - * will lose their values. Save the useful subset here. - * - * Assumption: the AP will not change the register values between the suspend - * and resume handlers being called! - */ -static void platform_mif_reg_save(struct platform_mif *platform) -{ - platform->mif_preserve.irq_bit_mask = __platform_mif_irq_bit_mask_read(platform); -} - -/* Restore MIF registers that may have been lost during suspend */ -static void platform_mif_reg_restore(struct platform_mif *platform) -{ - __platform_mif_irq_bit_mask_write(platform, platform->mif_preserve.irq_bit_mask); -} - -int platform_mif_suspend(struct scsc_mif_abs *interface) -{ - int r = 0; - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (platform->suspend_handler) - r = platform->suspend_handler(interface, platform->suspendresume_data); - - /* Save the MIF registers. - * This must be done last as the suspend_handler may use the MIF - */ - platform_mif_reg_save(platform); - - return r; -} - -void platform_mif_resume(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - s32 ret; - - /* Restore the MIF registers. - * This must be done first as the resume_handler may use the MIF. - */ - platform_mif_reg_restore(platform); -#ifdef CONFIG_SOC_EXYNOS9610 - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clear WLBT_ACTIVE_CLR flag\n"); - /* Clear WLBT_ACTIVE_CLR flag in WLBT_CTRL_NS */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, WLBT_ACTIVE_CLR, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret); - } -#endif - if (platform->resume_handler) - platform->resume_handler(interface, platform->suspendresume_data); -} diff --git a/drivers/misc/samsung/scsc/platform_mif_9630.c b/drivers/misc/samsung/scsc/platform_mif_9630.c deleted file mode 100644 index 169b4eda7cae..000000000000 --- a/drivers/misc/samsung/scsc/platform_mif_9630.c +++ /dev/null @@ -1,2217 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Implements interface */ - -#include "platform_mif.h" - -/* Interfaces it Uses */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_OF -#include -#include -#include -#endif -#include -#include -#include -#include -#include "mif_reg_S5E9630.h" -#include "platform_mif_module.h" -#ifdef CONFIG_ARCH_EXYNOS -#include -#endif -#ifdef CONFIG_SOC_EXYNOS9630 -#include -#endif - -#ifdef CONFIG_SCSC_SMAPPER -#include -#include "mif_reg_smapper.h" -#endif -#ifdef CONFIG_SCSC_QOS -#include -#endif - -#if !defined(CONFIG_SOC_EXYNOS9630) -#error Target processor CONFIG_SOC_EXYNOS9630 not selected -#endif - -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif -/* Time to wait for CFG_REQ IRQ on 9610 */ -#define WLBT_BOOT_TIMEOUT (HZ) - -#ifdef CONFIG_OF_RESERVED_MEM -#include -#endif -static unsigned long sharedmem_base; -static size_t sharedmem_size; - -#ifdef CONFIG_SCSC_CHV_SUPPORT -static bool chv_disable_irq; -module_param(chv_disable_irq, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(chv_disable_irq, "Do not register for irq"); -#endif - -static bool enable_platform_mif_arm_reset = true; -module_param(enable_platform_mif_arm_reset, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_platform_mif_arm_reset, "Enables WIFIBT ARM cores reset"); - -static bool disable_apm_setup; -module_param(disable_apm_setup, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(disable_apm_setup, "Disable host APM setup"); - -#ifdef CONFIG_SCSC_QOS -struct qos_table { - unsigned int freq_mif; - unsigned int freq_int; - unsigned int freq_cl0; - unsigned int freq_cl1; -}; -#endif - -struct platform_mif { - struct scsc_mif_abs interface; - struct scsc_mbox_s *mbox; - struct platform_device *pdev; - - struct device *dev; - - struct { - int irq_num; - int flags; - atomic_t irq_disabled_cnt; - } wlbt_irq[PLATFORM_MIF_NUM_IRQS]; - - /* MIF registers preserved during suspend */ - struct { - u32 irq_bit_mask; - } mif_preserve; - - /* register MBOX memory space */ - size_t reg_start; - size_t reg_size; - void __iomem *base; - - /* register CMU memory space */ - struct regmap *cmu_base; - - void __iomem *con0_base; - - /* pmu syscon regmap */ - struct regmap *pmureg; -#if defined(CONFIG_SOC_EXYNOS9630) - struct regmap *i3c_apm_pmic; - struct regmap *dbus_baaw; - struct regmap *pbus_baaw; - struct regmap *wlbt_remap; - struct regmap *boot_cfg; - - /* Signalled when CFG_REQ IRQ handled */ - struct completion cfg_ack; - - /* State of CFG_REQ handler */ - enum wlbt_boot_state { - WLBT_BOOT_IN_RESET = 0, - WLBT_BOOT_WAIT_CFG_REQ, - WLBT_BOOT_CFG_DONE, - WLBT_BOOT_CFG_ERROR - } boot_state; - -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER */ - void __iomem *smapper_base; - u8 smapper_banks; - struct { - u8 bank; - u32 ws; - bool large; - struct scsc_mif_smapper_info bank_info; - } *smapper; -#endif - /* Shared memory space - reserved memory */ - unsigned long mem_start; - size_t mem_size; - void __iomem *mem; - - /* Callback function and dev pointer mif_intr manager handler */ - void (*r4_handler)(int irq, void *data); - void *irq_dev; - /* spinlock to serialize driver access */ - spinlock_t mif_spinlock; - void (*reset_request_handler)(int irq, void *data); - void *irq_reset_request_dev; - -#ifdef CONFIG_SCSC_QOS - /* QoS table */ - struct qos_table *qos; - bool qos_enabled; -#endif - /* Suspend/resume handlers */ - int (*suspend_handler)(struct scsc_mif_abs *abs, void *data); - void (*resume_handler)(struct scsc_mif_abs *abs, void *data); - void *suspendresume_data; -}; - -static void power_supplies_on(struct platform_mif *platform); - -extern int mx140_log_dump(void); - -#define platform_mif_from_mif_abs(MIF_ABS_PTR) container_of(MIF_ABS_PTR, struct platform_mif, interface) - -inline void platform_mif_reg_write(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->base + offset); -} - -inline u32 platform_mif_reg_read(struct platform_mif *platform, u16 offset) -{ - return readl(platform->base + offset); -} - -#ifdef CONFIG_SCSC_SMAPPER -inline void platform_mif_reg_write_smapper(struct platform_mif *platform, u16 offset, u32 value) -{ - writel(value, platform->smapper_base + offset); -} - -inline u32 platform_mif_reg_read_smapper(struct platform_mif *platform, u16 offset) -{ - return readl(platform->smapper_base + offset); -} - -#define PLATFORM_MIF_SHIFT_SMAPPER_ADDR 11 /* From 36 bits addres to 25 bits */ -#define PLATFORM_MIF_SHIFT_SMAPPER_END 4 /* End address aligment */ - -/* Platform is responsible to give the phys mapping of the SMAPPER maps */ -static int platform_mif_smapper_get_mapping(struct scsc_mif_abs *interface, u8 *phy_map, u16 *align) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Mapping %d banks\n", platform->smapper_banks); - - if (!platform->smapper_banks) - return -EINVAL; - - for (i = 0; i < platform->smapper_banks; i++) { - if (platform->smapper[i].large) - phy_map[i] = SCSC_MIF_ABS_LARGE_BANK; - else - phy_map[i] = SCSC_MIF_ABS_SMALL_BANK; - } - - if (align) - *align = 1 << PLATFORM_MIF_SHIFT_SMAPPER_ADDR; - - return 0; -} - -static int platform_mif_smapper_get_bank_info(struct scsc_mif_abs *interface, u8 bank, struct scsc_mif_smapper_info *bank_info) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper_banks) - return -EINVAL; - - bank_info->num_entries = platform->smapper[bank].bank_info.num_entries; - bank_info->mem_range_bytes = platform->smapper[bank].bank_info.mem_range_bytes; - - return 0; -} - -static u8 platform_mif_smapper_granularity_to_bits(u32 granularity) -{ - if (granularity <= 2 * 1024) - return 0; - if (granularity <= 4 * 1024) - return 1; - if (granularity <= 8 * 1024) - return 2; - if (granularity <= 16 * 1024) - return 3; - if (granularity <= 32 * 1024) - return 4; - if (granularity <= 64 * 1024) - return 5; - if (granularity <= 128 * 1024) - return 6; - return 7; -} - -static u32 platform_mif_smapper_get_bank_base_address(struct scsc_mif_abs *interface, u8 bank) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform->smapper) - return 0; - - return platform->smapper[bank].ws; -} - -/* Configure smapper according the memory map and range */ -static void platform_mif_smapper_configure(struct scsc_mif_abs *interface, u32 granularity) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u8 gran; - u8 nb = platform->smapper_banks; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Configure SMAPPER with granularity %d\n", granularity); - - gran = platform_mif_smapper_granularity_to_bits(granularity); - - platform_mif_reg_write_smapper(platform, SMAPPER_QCH_DISABLE, 1); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AR, 0); - platform_mif_reg_write_smapper(platform, ORIGIN_ADDR_AW, 0); - /* Program SMAPPER memmap */ - for (i = 0; i < nb; i++) { - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(i), 0); - /* Set START_ADDR */ - platform_mif_reg_write_smapper(platform, START_ADDR(i), platform->smapper[i].ws); - /* Set ADDR_GRANULARITY - FIXED AT 4KB */ - platform_mif_reg_write_smapper(platform, ADDR_GRANULARITY(i), gran); - /* WLAN_ADDR_MAP operation is started */ - } - /* Set access window control (MSB 32bits Start/End address) */ - /* Remapped address should be ranged from AW_START_ADDR to AW_EN_ADDR */ - platform_mif_reg_write_smapper(platform, AW_START_ADDR, 0); - platform_mif_reg_write_smapper(platform, AW_END_ADDR, dma_get_mask(platform->dev) >> PLATFORM_MIF_SHIFT_SMAPPER_END); - smp_mb(); -} - -/* Caller is responsible of validating the phys address (alignment) */ -static int platform_mif_smapper_write_sram(struct scsc_mif_abs *interface, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - u32 rb; - - if (!platform->smapper_banks) - return -EINVAL; - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "SMAPPER not enabled\n"); - return -EINVAL; - } - - /* Set ADDR_MAP_EN to 1'b0*/ - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 0); - /* Write mapping table to SRAM. Each entry consists of 25 bits MSB address to remap */ - for (i = 0; i < num_entries; i++) { - if (!addr[i]) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ADDR IS NULL at bank %d entry %d/%d\n", bank, first_entry + i, num_entries); - return -EINVAL; - } - /* Set SRAM_WRITE_CTRL to 1'b1*/ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 1); - platform_mif_reg_write_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i), addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - /* check incorrect writings */ - platform_mif_reg_write_smapper(platform, SRAM_WRITE_CTRL(bank), 0); - rb = platform_mif_reg_read_smapper(platform, SRAM_BANK_INDEX(bank, first_entry + i)); - if (rb != addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "incorrect mapping detected rb 0x%x, addr 0x%x\n", rb, (u32)addr[i] >> PLATFORM_MIF_SHIFT_SMAPPER_ADDR); - return -EFAULT; - } - } - platform_mif_reg_write_smapper(platform, ADDR_MAP_EN(bank), 1); - smp_mb(); - return 0; -} - -static int platform_mif_parse_smapper(struct platform_mif *platform, struct device_node *np, u8 num_banks) -{ - /* SMAPPER parsing */ - struct device_node *np_banks; - char node_name[50]; - u32 val[2]; - u8 i; - u32 bank = 0, ws = 0, wsz = 0, ent = 0, large = 0; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "banks found: %d szof %zu\n", num_banks, sizeof(*platform->smapper)); - - platform->smapper = kmalloc_array(num_banks, sizeof(*platform->smapper), GFP_KERNEL); - - if (!platform->smapper) - return -ENOMEM; - - for (i = 0; i < num_banks; i++) { - snprintf(node_name, sizeof(node_name), "smapper_bank_%d", i); - np_banks = of_find_node_by_name(np, node_name); - if (!np_banks) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "%s: could not find smapper_bank\n", - node_name); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - of_property_read_u32(np_banks, "bank_num", &bank); - of_property_read_u32(np_banks, "fw_window_start", &ws); - of_property_read_u32(np_banks, "fw_window_size", &wsz); - of_property_read_u32(np_banks, "num_entries", &ent); - of_property_read_u32(np_banks, "is_large", &large); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "bank %d fw_w_start 0x%x fw_w_sz 0x%x entries %d is_large %d\n", - bank, ws, wsz, ent, large); - - platform->smapper[i].bank = (u8)bank; - platform->smapper[i].ws = ws; - platform->smapper[i].large = (bool)large; - platform->smapper[i].bank_info.num_entries = ent; - platform->smapper[i].bank_info.mem_range_bytes = wsz; - } - - /* Update the number of banks before returning */ - platform->smapper_banks = num_banks; - - of_property_read_u32_array(np, "smapper_reg", val, 2); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "smapper reg address 0x%x size 0x%x\n", val[0], val[1]); - platform->smapper_base = - devm_ioremap_nocache(platform->dev, val[0], val[1]); - - if (!platform->smapper_base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping smapper register region\n"); - kfree(platform->smapper); - platform->smapper = NULL; - return -ENOENT; - } - - return 0; -} -#endif -#ifdef CONFIG_SCSC_QOS -static int platform_mif_parse_qos(struct platform_mif *platform, struct device_node *np) -{ - int len, i; - - platform->qos_enabled = false; - - len = of_property_count_u32_elems(np, "qos_table"); - if (!(len == 12)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "No qos table for wlbt, or incorrect size\n"); - return -ENOENT; - } - - platform->qos = devm_kzalloc(platform->dev, sizeof(struct qos_table) * len / 4, GFP_KERNEL); - if (!platform->qos) - return -ENOMEM; - - of_property_read_u32_array(np, "qos_table", (unsigned int *)platform->qos, len); - - for (i = 0; i < len / 4; i++) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "QoS Table[%d] mif : %u int : %u cl0 : %u cl1: %u\n", i, - platform->qos[i].freq_mif, - platform->qos[i].freq_int, - platform->qos[i].freq_cl0, - platform->qos[i].freq_cl1); - } - - platform->qos_enabled = true; - return 0; -} - -struct qos_table platform_mif_pm_qos_get_table(struct platform_mif *platform, enum scsc_qos_config config) -{ - struct qos_table table; - - switch (config) { - case SCSC_QOS_MIN: - table.freq_mif = platform->qos[0].freq_mif; - table.freq_int = platform->qos[0].freq_int; - table.freq_cl0 = platform->qos[0].freq_cl0; - table.freq_cl1 = platform->qos[0].freq_cl1; - break; - - case SCSC_QOS_MED: - table.freq_mif = platform->qos[1].freq_mif; - table.freq_int = platform->qos[1].freq_int; - table.freq_cl0 = platform->qos[1].freq_cl0; - table.freq_cl1 = platform->qos[1].freq_cl1; - break; - - case SCSC_QOS_MAX: - table.freq_mif = platform->qos[2].freq_mif; - table.freq_int = platform->qos[2].freq_int; - table.freq_cl0 = platform->qos[2].freq_cl0; - table.freq_cl1 = platform->qos[2].freq_cl1; - break; - - default: - table.freq_mif = 0; - table.freq_int = 0; - table.freq_cl0 = 0; - table.freq_cl1 = 0; - } - - return table; -} - -static int platform_mif_pm_qos_add_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS add request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_add_request(&qos_req->pm_qos_req_mif, PM_QOS_BUS_THROUGHPUT, table.freq_mif); - pm_qos_add_request(&qos_req->pm_qos_req_int, PM_QOS_DEVICE_THROUGHPUT, table.freq_int); - pm_qos_add_request(&qos_req->pm_qos_req_cl0, PM_QOS_CLUSTER0_FREQ_MIN, table.freq_cl0); - pm_qos_add_request(&qos_req->pm_qos_req_cl1, PM_QOS_CLUSTER1_FREQ_MIN, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_update_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - struct qos_table table; - - if (!platform) - return -ENODEV; - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - table = platform_mif_pm_qos_get_table(platform, config); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "PM QoS update request: %u. MIF %u INT %u CL0 %u CL1 %u\n", config, table.freq_mif, table.freq_int, table.freq_cl0, table.freq_cl1); - - pm_qos_update_request(&qos_req->pm_qos_req_mif, table.freq_mif); - pm_qos_update_request(&qos_req->pm_qos_req_int, table.freq_int); - pm_qos_update_request(&qos_req->pm_qos_req_cl0, table.freq_cl0); - pm_qos_update_request(&qos_req->pm_qos_req_cl1, table.freq_cl1); - - return 0; -} - -static int platform_mif_pm_qos_remove_request(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (!platform) - return -ENODEV; - - - if (!platform->qos_enabled) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS not configured\n"); - return -EOPNOTSUPP; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PM QoS remove request\n"); - pm_qos_remove_request(&qos_req->pm_qos_req_mif); - pm_qos_remove_request(&qos_req->pm_qos_req_int); - pm_qos_remove_request(&qos_req->pm_qos_req_cl0); - pm_qos_remove_request(&qos_req->pm_qos_req_cl1); - - return 0; -} -#endif - -static void platform_mif_irq_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT handler not registered\n"); -} - -static void platform_mif_irq_reset_request_default_handler(int irq, void *data) -{ - /* Avoid unused parameter error */ - (void)irq; - (void)data; - - /* int handler not registered */ - SCSC_TAG_INFO_DEV(PLAT_MIF, NULL, "INT reset_request handler not registered\n"); -} - -irqreturn_t platform_mif_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "INT %pS\n", platform->r4_handler); - if (platform->r4_handler != platform_mif_irq_default_handler) - platform->r4_handler(irq, platform->irq_dev); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MIF Interrupt Handler not registered\n"); - - return IRQ_HANDLED; -} - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ -irqreturn_t platform_alive_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - - return IRQ_HANDLED; -} -#endif - -irqreturn_t platform_wdog_isr(int irq, void *data) -{ - int ret = 0; - struct platform_mif *platform = (struct platform_mif *)data; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - if (platform->reset_request_handler != platform_mif_irq_reset_request_default_handler) { - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - platform->reset_request_handler(irq, platform->irq_reset_request_dev); - } else { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG Interrupt reset_request_handler not registered\n"); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Disabling unhandled WDOG IRQ.\n"); - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_inc(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt); - } - - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - WLBT_RESET_REQ_CLR, WLBT_RESET_REQ_CLR); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clearing WLBT_RESET_REQ\n"); - if (ret < 0) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_RESET_REQ_CLR]: %d\n", ret); - - return IRQ_HANDLED; -} - -/* - * Attached array contains the replacement PMU boot code which should - * be programmed using the CBUS during the config phase. - */ -uint32_t ka_patch[] = { - // Maxwell142 PMU+PROC combined boot ROM - // IP Version: 0xA3 - // Major Version: 0xF, Minor Version: 0xF - // PMU ROM version: 0x4 - // PROC ROM version: 0x0 - // From excite 0605 - 0xe8750002, - 0x1189113f, - 0x0e807558, - 0xe030b3e5, - 0x11a230fb, - 0xb1f50774, - 0x75fdb2b5, - 0x077400b1, - 0xadb5acf5, - 0x01b443fd, - 0xe020b3e5, - 0xfeb453fb, - 0xd880a3d2, - 0x83798278, - 0xa075d280, - 0x78377907, - 0x0754e6b0, - 0x800207b4, - 0x04f6d90b, - 0x7580f5c4, - 0x038000af, - 0x22098075, - 0x53f7f753, - 0x0479fece, - 0xce53fed9, - 0xd90c79fd, - 0xfbce53fe, - 0x53b79275, - 0x0074fd91, - 0xce5392f5, - 0xb79275f7, - 0x5302f943, - 0xf922fef9, - 0xfbd8fed9, - 0x019e7522, - 0x7501d275, - 0xc17580d5, - 0x74047880, - 0x838012c3, - 0x78c0c175, - 0x12827402, - 0x80758380, - 0x0291750d, - 0x75039375, - 0xa975029e, - 0x00002201, -}; - -//extern bool reset_failed; - -irqreturn_t platform_cfg_req_isr(int irq, void *data) -{ - struct platform_mif *platform = (struct platform_mif *)data; - u64 ret64 = 0; - const u64 EXYNOS_WLBT = 0x1; - /*s32 ret = 0;*/ - unsigned int ka_addr = 0x1000; - uint32_t *ka_patch_addr = ka_patch; - u32 id; - -#define CHECK(x) do { \ - int retval = (x); \ - if (retval < 0) {\ - pr_err("%s failed at L%d", __FUNCTION__, __LINE__); \ - goto cfg_error; \ - } \ -} while (0) - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n"); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "disable_irq\n"); - - /* mask the irq */ - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - /* Was the CFG_REQ irq received from WLBT before we expected it? - * Typically this indicates an issue returning WLBT HW to reset. - */ - if (platform->boot_state != WLBT_BOOT_WAIT_CFG_REQ) { - u32 val; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Spurious CFG_REQ IRQ from WLBT!\n"); - - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_NS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_S 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - - //reset_failed = true; /* prevent further interaction with HW */ - - return IRQ_HANDLED; - } - - /* Set TZPC to non-secure mode */ - /* http://caeweb/~wshi/skylark/project-skylark.sim-basic/sky/regs/pmu_conf/pmu_conf/doc/main.html - */ - ret64 = exynos_smc(SMC_CMD_CONN_IF, (EXYNOS_WLBT << 32) | EXYNOS_SET_CONN_TZPC, 0, 0); - if (ret64) - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to set TZPC to non-secure mode: %llu\n", ret64); - else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SMC_CMD_CONN_IF run successfully : %llu\n", ret64); - - /* WLBT_REMAP PMU_REMAP - PROC_RMP_BOOT_ADDR 0x14450400 */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP begin\n"); - CHECK(regmap_write(platform->wlbt_remap, 0x400, WLBT_DBUS_BAAW_0_START >> 12)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT_REMAP end\n"); - - /* CHIP_VERSION_ID 0x14450410, - update with AP view of SOC revision */ - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "CHIP_VERSION_ID begin\n"); - regmap_read(platform->wlbt_remap, CHIP_VERSION_ID_OFFSET, &id); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Read CHIP_VERSION_ID 0x%x\n", id); - id &= ~(CHIP_VERSION_ID_IP_MAJOR | CHIP_VERSION_ID_IP_MINOR); - id |= ((exynos_soc_info.revision << CHIP_VERSION_ID_IP_MINOR_SHIFT) & (CHIP_VERSION_ID_IP_MAJOR | CHIP_VERSION_ID_IP_MINOR)); - CHECK(regmap_write(platform->wlbt_remap, CHIP_VERSION_ID_OFFSET, id)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Updated CHIP_VERSION_ID 0x%x\n", id); - - /* DBUS_BAAW regions */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW begin\n"); // PMU_DBUS_BAAW - - /* Shared DRAM mapping. The destination address is the location reserved - * by the kernel. - */ - CHECK(regmap_write(platform->dbus_baaw, 0x0, WLBT_DBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x4, WLBT_DBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->dbus_baaw, 0x8, platform->mem_start >> 12)); // FW AP base addr >> 12 - CHECK(regmap_write(platform->dbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); -#if 0 - /* Additional DRAM mappings for future use */ - CHECK(regmap_write(platform->dbus_baaw, 0x10, 0x000C0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x14, 0x000D0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x18, 0x000D0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x1C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->dbus_baaw, 0x20, 0x000D0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x24, 0x000E0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x28, 0x000E0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x2C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->dbus_baaw, 0x30, 0x000E0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x34, 0x000F0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x38, 0x000F0000)); - CHECK(regmap_write(platform->dbus_baaw, 0x3C, WLBT_BAAW_ACCESS_CTRL)); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "DBUS_BAAW end\n"); - - /* PBUS_BAAW regions */ - /* ref wlbt_if_S5E9630.c, updated for MX450 memory map */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW begin\n"); - - /* Range for CP2WLBT mailbox */ - CHECK(regmap_write(platform->pbus_baaw, 0x0, WLBT_CBUS_BAAW_0_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4, WLBT_CBUS_BAAW_0_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x8, WLBT_PBUS_MBOX_CP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0xC, WLBT_BAAW_ACCESS_CTRL)); - - /* Range includes AP2WLBT,APM2WLBT,GNSS2WLBT mailboxes */ - CHECK(regmap_write(platform->pbus_baaw, 0x10, WLBT_CBUS_BAAW_1_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x14, WLBT_CBUS_BAAW_1_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x18, WLBT_PBUS_MBOX_GNSS2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x1C, WLBT_BAAW_ACCESS_CTRL)); -#if 0 - /* These mappings are not yet used by WLBT FW */ - CHECK(regmap_write(platform->pbus_baaw, 0x20, WLBT_CBUS_BAAW_2_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x24, WLBT_CBUS_BAAW_2_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x28, WLBT_PBUS_GPIO_CMGP_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x2C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x30, WLBT_CBUS_BAAW_3_START >>12)); - CHECK(regmap_write(platform->pbus_baaw, 0x34, WLBT_CBUS_BAAW_3_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x38, WLBT_PBUS_SYSREG_CMGP2WLBT_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x3C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x40, WLBT_CBUS_BAAW_4_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x44, WLBT_CBUS_BAAW_4_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x48, WLBT_PBUS_USI_CMG00_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x4C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x50, WLBT_CBUS_BAAW_5_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x54, WLBT_CBUS_BAAW_5_END >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x58, WLBT_PBUS_CHUB_USICHUB0_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x5C, WLBT_BAAW_ACCESS_CTRL)); - - CHECK(regmap_write(platform->pbus_baaw, 0x60, WLBT_CBUS_BAAW_6_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x64, WLBT_CBUS_BAAW_6_START >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x68, WLBT_PBUS_CHUB_BASE >> 12)); - CHECK(regmap_write(platform->pbus_baaw, 0x6C, WLBT_BAAW_ACCESS_CTRL)); -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "PBUS_BAAW end\n"); - - /* PMU boot patch */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT begin\n"); - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x1)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_WLBT done\n"); - - while (ka_patch_addr < (ka_patch + ARRAY_SIZE(ka_patch))) { - CHECK(regmap_write(platform->boot_cfg, ka_addr, *ka_patch_addr)); - ka_addr += sizeof(ka_patch[0]); - ka_patch_addr++; - } - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "KA patch done\n"); - - /* Notify PMU of configuration done */ - CHECK(regmap_write(platform->boot_cfg, 0x0, 0x0)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT config done\n"); - - /* BOOT_CFG_ACK */ - CHECK(regmap_write(platform->boot_cfg, 0x4, 0x1)); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "BOOT_CFG_ACK done\n"); - - /* Delay to allow HW to clear CFG_REQ and hence de-assert IRQ, which - * it does in response to CFG_ACK - */ - //udelay(100); - - /* Release ownership of MASK_PWR_REQ */ - /* See sequence in 9.6.6 */ - /*ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, - MASK_PWR_REQ, 0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to clear WLBT_CTRL_NS[MASK_PWR_REQ]: %d\n", ret); - goto cfg_error; - }*/ - - /* Mark as CFQ_REQ handled, so boot may continue */ - platform->boot_state = WLBT_BOOT_CFG_DONE; - - /* Signal triggering function that the IRQ arrived and CFG was done */ - complete(&platform->cfg_ack); - - /* Re-enable IRQ here to allow spurious interrupt to be tracked */ - enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - /* as per wlbt_if_S5E9630.c - end */ - return IRQ_HANDLED; -cfg_error: - platform->boot_state = WLBT_BOOT_CFG_ERROR; - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "ERROR: WLBT Config failed. WLBT will not work\n"); - complete(&platform->cfg_ack); - return IRQ_HANDLED; -} - -static void platform_mif_unregister_irq(struct platform_mif *platform) -{ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering IRQs\n"); - - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform); - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform); - /* Reset irq_disabled_cnt for WDOG IRQ since the IRQ itself is here unregistered and disabled */ - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* if ALIVE irq is required */ - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform); -#endif - devm_free_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform); -} - -static int platform_mif_register_irq(struct platform_mif *platform) -{ - int err; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering IRQs\n"); - - /* Register MBOX irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering MBOX irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform->wlbt_irq[PLATFORM_MIF_MBOX].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_MBOX].irq_num, platform_mif_isr, - platform->wlbt_irq[PLATFORM_MIF_MBOX].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register MBOX handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - - /* Register WDOG irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering WDOG irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform->wlbt_irq[PLATFORM_MIF_WDOG].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num, platform_wdog_isr, - platform->wlbt_irq[PLATFORM_MIF_WDOG].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register WDOG handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - -#ifdef CONFIG_SCSC_ENABLE_ALIVE_IRQ - /* Register ALIVE irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering ALIVE irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_ALIVE].irq_num, platform_alive_isr, - platform->wlbt_irq[PLATFORM_MIF_ALIVE].flags, DRV_NAME, platform); - if (IS_ERR_VALUE(err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register ALIVE handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } -#endif - - /* Mark as WLBT in reset before enabling IRQ to guard against spurious IRQ */ - platform->boot_state = WLBT_BOOT_IN_RESET; - smp_wmb(); /* commit before irq */ - - /* Register WB2AP_CFG_REQ irq */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering CFG_REQ irq: %d flag 0x%x\n", - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags); - - err = devm_request_irq(platform->dev, platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num, platform_cfg_req_isr, - platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].flags, DRV_NAME, platform); - if (IS_ERR_VALUE((unsigned long)err)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to register CFG_REQ handler: %d. Aborting.\n", err); - err = -ENODEV; - return err; - } - - /* Leave disabled until ready to handle */ - disable_irq_nosync(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - return 0; -} - -static void platform_mif_destroy(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - platform_mif_unregister_irq(platform); -} - -static char *platform_mif_get_uid(struct scsc_mif_abs *interface) -{ - /* Avoid unused parameter error */ - (void)interface; - return "0"; -} - -static void wlbt_regdump(struct platform_mif *platform) -{ - u32 val = 0; - - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_S 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CONFIGURATION 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_CTRL_NS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_CTRL_NS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_IN, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_IN 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_OUT, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_OUT 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATUS 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_STATES, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATES 0x%x\n", val); - - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - -#if 0 - /* Delay to let PMU process the cfg_ack */ - udelay(10000); - regmap_read(platform->boot_cfg, 0x0, &val); - SCSC_TAG_INFO(PLAT_MIF, "BOOT_SOURCE 0x%x\n", val); - - regmap_read(platform->boot_cfg, 0x4, &val); - SCSC_TAG_INFO(PLAT_MIF, "BOOT_CFG_ACK 0x%x\n", val); -#endif -} - -/* WLBT START */ -static int platform_mif_start(struct scsc_mif_abs *interface, bool start) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - /* done as part of platform_mif_pmu_reset_release() init_done sequence */ -#if 0 - //s32 ret = 0; - if (start) - val = WLBT_START; - - /* See sequence in TODO update when available */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S, - WLBT_START, val); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret); - return ret; - } - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "update WIFI_CTRL_S[WLBT_START]: %d\n", ret); - -#endif - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "start %d\n", start); - /* At this point WLBT should assert the CFG_REQ IRQ, so wait for it */ - if (start && - wait_for_completion_timeout(&platform->cfg_ack, WLBT_BOOT_TIMEOUT) == 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Timeout waiting for CFG_REQ IRQ\n"); - wlbt_regdump(platform); - return -ETIMEDOUT; - } - - wlbt_regdump(platform); - - /* only continue if CFG_REQ IRQ configured WLBT/PMU correctly */ - if (platform->boot_state == WLBT_BOOT_CFG_ERROR) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "CFG_REQ failed to configure WLBT.\n"); - return -EIO; - } - return 0; -} - -static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - int ret = 0; - u32 val = 0; - u32 v = 0; - unsigned long timeout; - static bool init_done; - - /* We're now ready for the IRQ */ - platform->boot_state = WLBT_BOOT_WAIT_CFG_REQ; - smp_wmb(); /* commit before irq */ - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "on boot_state = WLBT_BOOT_WAIT_CFG_REQ\n"); - - /* INIT SEQUENCE - First WLBT boot only - * Cold reset wrt. AP power sequencer, cold reset for WLBT - */ - if (!init_done) { - /* init sequence from excite - * //20190812 APM team Change PMUCAL guide doc. - * SetBits((uinteger)REG_WLBT_CTRL_S, 3, 0x1, 0x1); - * SetBits((uinteger)REG_WLBT_OPTION, 3, 0x1, 0x1); - * udelay(1000); - * SetBits((uinteger)SYSTEM_OUT, 9, 0x1, 0x1); - * SetBits((uinteger)REG_WLBT_CONFIGURATION, 0, 0x1, 0x1); - * while (GetBits((uinteger)REG_VGPIO_TX_MONITOR, 29, 0x1) != 0x1) - * ; - * while (GetBits((uinteger)REG_WLBT_STATUS, 0, 0x1) != 0x1) - * ; - * while (GetBits((uinteger)REG_WLBT_IN, 4, 0x1) != 0x1) - * ; - */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "init\n"); - - /* WLBT_CTRL_S[WLBT_START] = 1 enable */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S, - WLBT_START, WLBT_START); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CTRL_S, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CTRL_S[WLBT_START]: 0x%x\n", val); - - /* WLBT_OPTION[WLBT_OPTION_DATA] = 1 Power On */ - ret = regmap_update_bits(platform->pmureg, WLBT_OPTION, - WLBT_OPTION_DATA, WLBT_OPTION_DATA); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_OPTION[WLBT_OPTION_DATA]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_OPTION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_OPTION[WLBT_OPTION_DATA]: 0x%x\n", val); - - /* SYSTEM_OUT[PWRRGTON_CON] = 1 Power On */ - ret = regmap_update_bits(platform->pmureg, SYSTEM_OUT, - PWRRGTON_CON, PWRRGTON_CON); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update SYSTEM_OUT[PWRRGTON_CON]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, SYSTEM_OUT, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully SYSTEM_OUT[PWRRGTON_CON]: 0x%x\n", val); - - /* WLBT_CONFIGURATION[LOCAL_PWR_CFG] = 1 Power On */ - ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION, - LOCAL_PWR_CFG, LOCAL_PWR_CFG); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CONFIGURATION[PWRRGTON_CON]: 0x%x\n", val); - - /* VGPIO_TX_MONITOR[VGPIO_TX_MON_BIT29] = 0x1 */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - val &= (u32)VGPIO_TX_MON_BIT29; - if (val) { - SCSC_TAG_INFO(PLAT_MIF, "VGPIO_TX_MONITOR 0x%x\n", val); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for VGPIO_TX_MONITOR time-out: " - "VGPIO_TX_MONITOR 0x%x\n", val); - } - - /* wait for power up complete WLBT_STATUS[WLBT_STATUS_BIT0] = 1 for Power On */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - val &= (u32)WLBT_STATUS_BIT0; - if (val) { - /* Power On complete */ - SCSC_TAG_INFO(PLAT_MIF, "Power On complete: WLBT_STATUS 0x%x\n", val); - /* re affirming power on by reading WLBT_STATES */ - /* STATES[7:0] = 0x10 for Power Up */ - regmap_read(platform->pmureg, WLBT_STATES, &v); - SCSC_TAG_INFO(PLAT_MIF, "Power On complete: WLBT_STATES 0x%x\n", v); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for power on time-out: " - "WLBT_STATUS 0x%x, WLBT_STATES 0x%x\n", val, v); - } - - /* wait for WLBT_IN[BUS_READY] = 1 for BUS READY state */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_IN, &val); - val &= (u32)BUS_READY; - if (val) { - /* BUS ready indication signal -> 1: BUS READY state */ - SCSC_TAG_INFO(PLAT_MIF, "Bus Ready: WLBT_IN 0x%x\n", val); - - /* OK to break */ - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->pmureg, WLBT_IN, &val); - SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for Bus Ready: WLBT_IN 0x%x\n", val); - } - - init_done = true; - - goto init_code_done; - } - - /* RESET RELEASE - Subsequent WLBT reboots */ - /* wlbt_if_reset_release - from excite code - * 20190812 APM team Change PMUCAL guide doc. - * SetBits((uinteger)REG_WLBT_CONFIGURATION, 0, 0x1, 0x1); - * while (GetBits((uinteger)REG_WLBT_STATUS, 0, 0x1) != 0x1) - * ; - * while (GetBits((uinteger)REG_WLBT_IN, 4, 0x1) != 0x1) - ; - */ - - /* Warm reset wrt. AP power sequencer, but cold reset for WLBT */ - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "release\n"); - - /* Power Down */ - ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION, - LOCAL_PWR_CFG, 0x1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CONFIGURATION[LOCAL_PWR_CFG]: 0x%x\n", val); - - /* wait for power up complete WLBT_STATUS[0] = 0 for power down */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - val &= (u32)WLBT_STATUS_BIT0; - if (val) { - /* Power up complete */ - SCSC_TAG_INFO(PLAT_MIF, "Power up complete: WLBT_STATUS 0x%x\n", val); - /* re affirming power down by reading WLBT_STATES */ - /* STATES[7:0] = 0x80 for Power Down */ - regmap_read(platform->pmureg, WLBT_STATES, &v); - SCSC_TAG_INFO(PLAT_MIF, "Power up complete: WLBT_STATES 0x%x\n", v); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "Timeout waiting for Power up complete: " - "WLBT_STATUS 0x%x, WLBT_STATES 0x%x\n", val, v); - } - - /* wait for WLBT_IN[BUS_READY] = 0 for BUS RESET RELEASED state */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_IN, &val); - val &= (u32)BUS_READY; - if (val) { - /* BUS ready indication signal -> 1: BUS RESET RELEASED Normal state */ - SCSC_TAG_INFO(PLAT_MIF, "Bus Ready: WLBT_IN 0x%x\n", val); - - /* OK to break */ - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->pmureg, WLBT_IN, &val); - SCSC_TAG_INFO(PLAT_MIF, "Timeout waiting for Bus Ready: WLBT_IN 0x%x != 0\n", val); - } - -init_code_done: - /* Now handle the CFG_REQ IRQ */ - enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num); - - ret = platform_mif_start(interface, true); - if (ret) - return ret; - - return ret; -} - -static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long timeout; - int ret; - u32 val; - - /* wlbt_if_reset_assertion() - from wlbt_if_S5E9630.c - * 20190812 APM team Change PMUCAL guide doc. - * SetBits((uinteger)REG_WLBT_OPTION, 3, 0x1, 0x1); - * SetBits((uinteger)SYSTEM_OUT, 9, 0x1, 0x1); - * while (GetBits((uinteger)REG_VGPIO_TX_MONITOR, 29, 0x1) != 0x1) - * ; - * udelay(1000); - * SetBits((uinteger)REG_WLBT_CONFIGURATION, 0, 0x1, 0x0); - * udelay(1000); - * while (GetBits((uinteger)REG_WLBT_STATUS, 0, 0x1) != 0x0) - * ; - */ - - ret = regmap_update_bits(platform->pmureg, WLBT_OPTION, - WLBT_OPTION_DATA, WLBT_OPTION_DATA); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_OPTION[WLBT_OPTION_DATA]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_OPTION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_OPTION[WLBT_OPTION_DATA]: 0x%x\n", val); - - ret = regmap_update_bits(platform->pmureg, SYSTEM_OUT, - PWRRGTON_CON, PWRRGTON_CON); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update SYSTEM_OUT[PWRRGTON_CON]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, SYSTEM_OUT, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully SYSTEM_OUT[PWRRGTON_CON]: 0x%x\n", val); - - /* VGPIO_TX_MONITOR = 0x1 */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - val &= (u32)VGPIO_TX_MON_BIT29; - if (val) { - SCSC_TAG_INFO(PLAT_MIF, "VGPIO_TX_MONITOR 0x%x\n", val); - break; - } - } while (time_before(jiffies, timeout)); - - if (!val) { - regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val); - SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for VGPIO_TX_MONITOR time-out: " - "VGPIO_TX_MONITOR 0x%x\n", val); - } - - /* Power Down */ - ret = regmap_write_bits(platform->pmureg, WLBT_CONFIGURATION, - LOCAL_PWR_CFG, 0x0); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret); - return ret; - } - regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "updated successfully WLBT_CONFIGURATION[LOCAL_PWR_CFG]: 0x%x\n", val); - - /* Wait for power Off WLBT_STATUS[WLBT_STATUS_BIT0] = 0 */ - timeout = jiffies + msecs_to_jiffies(500); - do { - regmap_read(platform->pmureg, WLBT_STATUS, &val); - val &= (u32)WLBT_STATUS_BIT0; - if (val == 0) { - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATUS 0x%x\n", val); - /* re affirming power down by reading WLBT_STATES */ - /* STATES[7:0] = 0x80 for Power Down */ - regmap_read(platform->pmureg, WLBT_STATES, &val); - SCSC_TAG_INFO(PLAT_MIF, "Power down complete: WLBT_STATES 0x%x\n", val); - - return 0; /* OK - return */ - } - } while (time_before(jiffies, timeout)); - - /* Timed out */ - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Timeout waiting for WLBT_STATUS status\n"); - - regmap_read(platform->pmureg, WLBT_STATUS, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATUS 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_DEBUG, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_DEBUG 0x%x\n", val); - regmap_read(platform->pmureg, WLBT_STATES, &val); - SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATES 0x%x\n", val); - return -ETIME; -} - -/* reset=0 - release from reset */ -/* reset=1 - hold reset */ -static int platform_mif_reset(struct scsc_mif_abs *interface, bool reset) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 ret = 0; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (enable_platform_mif_arm_reset || !reset) { - if (!reset) { /* Release from reset */ -#ifdef CONFIG_ARCH_EXYNOS - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "SOC_VERSION: product_id 0x%x, rev 0x%x\n", - exynos_soc_info.product_id, exynos_soc_info.revision); -#endif - power_supplies_on(platform); - - ret = platform_mif_pmu_reset_release(interface); - } else { - /* Put back into reset */ - ret = platform_mif_pmu_reset_assert(interface); - } - } else - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Not resetting ARM Cores - enable_platform_mif_arm_reset: %d\n", - enable_platform_mif_arm_reset); - return ret; -} - -static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size) -{ - int i; - struct page **pages; - void *vmem; - - size = PAGE_ALIGN(size); - - pages = kmalloc((size >> PAGE_SHIFT) * sizeof(*pages), GFP_KERNEL); - if (!pages) - return NULL; - - /* Map NORMAL_NC pages with kernel virtual space */ - for (i = 0; i < (size >> PAGE_SHIFT); i++) { - pages[i] = phys_to_page(phys_addr); - phys_addr += PAGE_SIZE; - } - - vmem = vmap(pages, size >> PAGE_SHIFT, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); - - kfree(pages); - return (void __iomem *)vmem; -} - -static void platform_mif_unmap_region(void *vmem) -{ - vunmap(vmem); -} - -static void *platform_mif_map(struct scsc_mif_abs *interface, size_t *allocated) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u8 i; - - if (allocated) - *allocated = 0; - - platform->mem = - platform_mif_map_region(platform->mem_start, platform->mem_size); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Error remaping shared memory\n"); - return NULL; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Map: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - - /* Initialise MIF registers with documented defaults */ - /* MBOXes */ - for (i = 0; i < NUM_MBOX_PLAT; i++) - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(ISSR(i)), 0x00000000); - - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); - -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_disable_irq == true) { - if (allocated) - *allocated = platform->mem_size; - return platform->mem; - } -#endif - /* register interrupts */ - if (platform_mif_register_irq(platform)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - return NULL; - } - - if (allocated) - *allocated = platform->mem_size; - /* Set the CR4 base address in Mailbox??*/ - return platform->mem; -} - -/* HERE: Not sure why mem is passed in - its stored in platform - as it should be */ -static void platform_mif_unmap(struct scsc_mif_abs *interface, void *mem) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - /* Avoid unused parameter error */ - (void)mem; - - /* MRs */ /*1's - set all as Masked */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR1), 0x0000ffff); - -#ifdef CONFIG_SCSC_CHV_SUPPORT - /* Restore PIO changed by Maxwell subsystem */ - if (chv_disable_irq == false) - /* Unregister IRQs */ - platform_mif_unregister_irq(platform); -#else - platform_mif_unregister_irq(platform); -#endif - /* CRs */ /* 1's - clear all the interrupts */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), 0xffff0000); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR1), 0x0000ffff); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unmap: virt %p phys %lx\n", platform->mem, (uintptr_t)platform->mem_start); - platform_mif_unmap_region(platform->mem); - platform->mem = NULL; -} - -static u32 platform_mif_irq_bit_mask_status_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INTMR0: 0x%x\n", val); - return val; -} - -static u32 platform_mif_irq_get(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - - /* Function has to return the interrupts that are enabled *AND* not masked */ - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0)) >> 16; - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Getting INT-INTMSR0: 0x%x\n", val); - - return val; -} - -static void platform_mif_irq_bit_set(struct scsc_mif_abs *interface, int bit_num, enum scsc_mif_abs_target target) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 reg; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - - reg = INTGR1; - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(reg), (1 << bit_num)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTGR1: bit %d on target %d\n", bit_num, target); -} - -static void platform_mif_irq_bit_clear(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - /* WRITE : 1 = Clears Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTCR0), ((1 << bit_num) << 16)); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTCR0: bit %d\n", bit_num); -} - -static void platform_mif_irq_bit_mask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 1 = Mask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val | ((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Setting INTMR0: 0x%x bit %d\n", val | (1 << bit_num), bit_num); -} - -static void platform_mif_irq_bit_unmask(struct scsc_mif_abs *interface, int bit_num) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 val; - unsigned long flags; - - if (bit_num >= 16) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Incorrect INT number: %d\n", bit_num); - return; - } - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - /* WRITE : 0 = Unmask Interrupt */ - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val & ~((1 << bit_num) << 16)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "UNMASK Setting INTMR0: 0x%x bit %d\n", val & ~((1 << bit_num) << 16), bit_num); -} - -/* Return the contents of the mask register */ -static u32 __platform_mif_irq_bit_mask_read(struct platform_mif *platform) -{ - u32 val; - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - val = platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0)); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Read INTMR0: 0x%x\n", val); - - return val; -} - -/* Write the mask register, destroying previous contents */ -static void __platform_mif_irq_bit_mask_write(struct platform_mif *platform, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform_mif_reg_write(platform, MAILBOX_WLBT_REG(INTMR0), val); - spin_unlock_irqrestore(&platform->mif_spinlock, flags); - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "Write INTMR0: 0x%x\n", val); -} - -static void platform_mif_irq_reg_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif int handler %pS in %p %p\n", handler, platform, interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = handler; - platform->irq_dev = dev; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif int handler %pS\n", interface); - spin_lock_irqsave(&platform->mif_spinlock, flags); - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_irq_reg_reset_request_handler(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif reset_request int handler %pS in %p %p\n", handler, platform, interface); - platform->reset_request_handler = handler; - platform->irq_reset_request_dev = dev; - if (atomic_read(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt)) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, - "Default WDOG handler disabled by spurios IRQ...re-enabling.\n"); - enable_irq(platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_num); - atomic_set(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt, 0); - } -} - -static void platform_mif_irq_unreg_reset_request_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "UnRegistering mif reset_request int handler %pS\n", interface); - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; -} - -static void platform_mif_suspend_reg_handler(struct scsc_mif_abs *interface, - int (*suspend)(struct scsc_mif_abs *abs, void *data), - void (*resume)(struct scsc_mif_abs *abs, void *data), - void *data) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Registering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = suspend; - platform->resume_handler = resume; - platform->suspendresume_data = data; -} - -static void platform_mif_suspend_unreg_handler(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Unregistering mif suspend/resume handlers in %p %p\n", platform, interface); - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; -} - -static u32 *platform_mif_get_mbox_ptr(struct scsc_mif_abs *interface, u32 mbox_index) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - u32 *addr; - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "mbox_index 0x%x\n", mbox_index); - addr = platform->base + MAILBOX_WLBT_REG(ISSR(mbox_index)); - return addr; -} - -static int platform_mif_get_mifram_ref(struct scsc_mif_abs *interface, void *ptr, scsc_mifram_ref *ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return -ENOMEM; - } - - /* Check limits! */ - if (ptr >= (platform->mem + platform->mem_size)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Unable to get pointer reference\n"); - return -ENOMEM; - } - - *ref = (scsc_mifram_ref)((uintptr_t)ptr - (uintptr_t)platform->mem); - - return 0; -} - -static void *platform_mif_get_mifram_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - /* Check limits */ - if (ref >= 0 && ref < platform->mem_size) - return (void *)((uintptr_t)platform->mem + (uintptr_t)ref); - else - return NULL; -} - -static void *platform_mif_get_mifram_phy_ptr(struct scsc_mif_abs *interface, scsc_mifram_ref ref) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - if (!platform->mem_start) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Memory unmmaped\n"); - return NULL; - } - - return (void *)((uintptr_t)platform->mem_start + (uintptr_t)ref); -} - -static uintptr_t platform_mif_get_mif_pfn(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - return vmalloc_to_pfn(platform->mem); -} - -static struct device *platform_mif_get_mif_device(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - SCSC_TAG_DEBUG_DEV(PLAT_MIF, platform->dev, "\n"); - - return platform->dev; -} - -static void platform_mif_irq_clear(void) -{ - /* Implement if required */ -} - -static int platform_mif_read_register(struct scsc_mif_abs *interface, u64 id, u32 *val) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (id == SCSC_REG_READ_WLBT_STAT) { - regmap_read(platform->pmureg, WLBT_STAT, val); - return 0; - } - - return -EIO; -} - -static void platform_mif_dump_register(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - unsigned long flags; - - spin_lock_irqsave(&platform->mif_spinlock, flags); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTGR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTGR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTCR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTCR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTSR1))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR0 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR0))); - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INTMSR1 0x%08x\n", platform_mif_reg_read(platform, MAILBOX_WLBT_REG(INTMSR1))); - - spin_unlock_irqrestore(&platform->mif_spinlock, flags); -} - -static void platform_mif_cleanup(struct scsc_mif_abs *interface) -{ -} - -static void platform_mif_restart(struct scsc_mif_abs *interface) -{ -} - -#ifdef CONFIG_OF_RESERVED_MEM -static int __init platform_mif_wifibt_if_reserved_mem_setup(struct reserved_mem *remem) -{ - SCSC_TAG_DEBUG(PLAT_MIF, "memory reserved: mem_base=%#lx, mem_size=%zd\n", - (unsigned long)remem->base, (size_t)remem->size); - - sharedmem_base = remem->base; - sharedmem_size = remem->size; - return 0; -} -RESERVEDMEM_OF_DECLARE(wifibt_if, "exynos,wifibt_if", platform_mif_wifibt_if_reserved_mem_setup); -#endif - -struct scsc_mif_abs *platform_mif_create(struct platform_device *pdev) -{ - struct scsc_mif_abs *platform_if; - struct platform_mif *platform = - (struct platform_mif *)devm_kzalloc(&pdev->dev, sizeof(struct platform_mif), GFP_KERNEL); - int err = 0; - u8 i = 0; - struct resource *reg_res; - -#ifdef CONFIG_SCSC_SMAPPER - u32 smapper_banks = 0; -#endif - - if (!platform) - return NULL; - - SCSC_TAG_INFO_DEV(PLAT_MIF, &pdev->dev, "Creating MIF platform device\n"); - - platform_if = &platform->interface; - - /* initialise interface structure */ - platform_if->destroy = platform_mif_destroy; - platform_if->get_uid = platform_mif_get_uid; - platform_if->reset = platform_mif_reset; - platform_if->map = platform_mif_map; - platform_if->unmap = platform_mif_unmap; - platform_if->irq_bit_set = platform_mif_irq_bit_set; - platform_if->irq_get = platform_mif_irq_get; - platform_if->irq_bit_mask_status_get = platform_mif_irq_bit_mask_status_get; - platform_if->irq_bit_clear = platform_mif_irq_bit_clear; - platform_if->irq_bit_mask = platform_mif_irq_bit_mask; - platform_if->irq_bit_unmask = platform_mif_irq_bit_unmask; - platform_if->irq_reg_handler = platform_mif_irq_reg_handler; - platform_if->irq_unreg_handler = platform_mif_irq_unreg_handler; - platform_if->irq_reg_reset_request_handler = platform_mif_irq_reg_reset_request_handler; - platform_if->irq_unreg_reset_request_handler = platform_mif_irq_unreg_reset_request_handler; - platform_if->suspend_reg_handler = platform_mif_suspend_reg_handler; - platform_if->suspend_unreg_handler = platform_mif_suspend_unreg_handler; - platform_if->get_mbox_ptr = platform_mif_get_mbox_ptr; - platform_if->get_mifram_ptr = platform_mif_get_mifram_ptr; - platform_if->get_mifram_ref = platform_mif_get_mifram_ref; - platform_if->get_mifram_pfn = platform_mif_get_mif_pfn; - platform_if->get_mifram_phy_ptr = platform_mif_get_mifram_phy_ptr; - platform_if->get_mif_device = platform_mif_get_mif_device; - platform_if->irq_clear = platform_mif_irq_clear; - platform_if->mif_dump_registers = platform_mif_dump_register; - platform_if->mif_read_register = platform_mif_read_register; - platform_if->mif_cleanup = platform_mif_cleanup; - platform_if->mif_restart = platform_mif_restart; -#ifdef CONFIG_SCSC_SMAPPER - platform_if->mif_smapper_get_mapping = platform_mif_smapper_get_mapping; - platform_if->mif_smapper_get_bank_info = platform_mif_smapper_get_bank_info; - platform_if->mif_smapper_write_sram = platform_mif_smapper_write_sram; - platform_if->mif_smapper_configure = platform_mif_smapper_configure; - platform_if->mif_smapper_get_bank_base_address = platform_mif_smapper_get_bank_base_address; -#endif -#ifdef CONFIG_SCSC_QOS - platform_if->mif_pm_qos_add_request = platform_mif_pm_qos_add_request; - platform_if->mif_pm_qos_update_request = platform_mif_pm_qos_update_request; - platform_if->mif_pm_qos_remove_request = platform_mif_pm_qos_remove_request; -#endif - /* Update state */ - platform->pdev = pdev; - platform->dev = &pdev->dev; - - platform->r4_handler = platform_mif_irq_default_handler; - platform->irq_dev = NULL; - platform->reset_request_handler = platform_mif_irq_reset_request_default_handler; - platform->irq_reset_request_dev = NULL; - platform->suspend_handler = NULL; - platform->resume_handler = NULL; - platform->suspendresume_data = NULL; - -#ifdef CONFIG_OF_RESERVED_MEM - platform->mem_start = sharedmem_base; - platform->mem_size = sharedmem_size; -#else - /* If CONFIG_OF_RESERVED_MEM is not defined, sharedmem values should be - * parsed from the scsc_wifibt binding - */ - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-base", &sharedmem_base)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_start = sharedmem_base; - - if (of_property_read_u32(pdev->dev.of_node, "sharedmem-size", &sharedmem_size)) { - err = -EINVAL; - goto error_exit; - } - platform->mem_size = sharedmem_size; -#endif -#ifdef CONFIG_SCSC_SMAPPER - platform->smapper = NULL; -#endif - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->mem_start 0x%x platform->mem_size 0x%x\n", - (u32)platform->mem_start, (u32)platform->mem_size); - if (platform->mem_start == 0) - SCSC_TAG_WARNING_DEV(PLAT_MIF, platform->dev, "platform->mem_start is 0"); - - if (platform->mem_size == 0) { - /* We return return if mem_size is 0 as it does not make any sense. - * This may be an indication of an incorrect platform device binding. - */ - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "platform->mem_size is 0"); - err = -EINVAL; - goto error_exit; - } - - /* Memory resource - Phys Address of MAILBOX_WLBT register map */ - reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!reg_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error getting mem resource for MAILBOX_WLBT\n"); - err = -ENOENT; - goto error_exit; - } - - platform->reg_start = reg_res->start; - platform->reg_size = resource_size(reg_res); - - platform->base = - devm_ioremap_nocache(platform->dev, reg_res->start, resource_size(reg_res)); - - if (!platform->base) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Error mapping register region\n"); - err = -EBUSY; - goto error_exit; - } - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "platform->reg_start %lx size %x base %p\n", - (uintptr_t)platform->reg_start, (u32)platform->reg_size, platform->base); - - /* Get the 4 IRQ resources */ - for (i = 0; i < 4; i++) { - struct resource *irq_res; - int irqtag; - - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!irq_res) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "No IRQ resource at index %d\n", i); - err = -ENOENT; - goto error_exit; - } - - if (!strcmp(irq_res->name, "MBOX")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "MBOX irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_MBOX; - } else if (!strcmp(irq_res->name, "ALIVE")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "ALIVE irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_ALIVE; - } else if (!strcmp(irq_res->name, "WDOG")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WDOG irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_WDOG; - } else if (!strcmp(irq_res->name, "CFG_REQ")) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "CFG_REQ irq %d flag 0x%x\n", - (u32)irq_res->start, (u32)irq_res->flags); - irqtag = PLATFORM_MIF_CFG_REQ; - } else { - SCSC_TAG_ERR_DEV(PLAT_MIF, &pdev->dev, "Invalid irq res name: %s\n", - irq_res->name); - err = -EINVAL; - goto error_exit; - } - platform->wlbt_irq[irqtag].irq_num = irq_res->start; - platform->wlbt_irq[irqtag].flags = (irq_res->flags & IRQF_TRIGGER_MASK); - atomic_set(&platform->wlbt_irq[irqtag].irq_disabled_cnt, 0); - } - - /* PMU reg map - syscon */ - platform->pmureg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,syscon-phandle"); - if (IS_ERR(platform->pmureg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "syscon regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->pmureg)); - err = -EINVAL; - goto error_exit; - } - - /* Completion event and state used to indicate CFG_REQ IRQ occurred */ - init_completion(&platform->cfg_ack); - platform->boot_state = WLBT_BOOT_IN_RESET; - - /* I3C_APM_PMIC */ - platform->i3c_apm_pmic = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,i3c_apm_pmic-syscon-phandle"); - if (IS_ERR(platform->i3c_apm_pmic)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "i3c_apm_pmic regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->i3c_apm_pmic)); - err = -EINVAL; - goto error_exit; - } - - /* DBUS_BAAW */ - platform->dbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,dbus_baaw-syscon-phandle"); - if (IS_ERR(platform->dbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "dbus_baaw regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->dbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* PBUS_BAAW */ - platform->pbus_baaw = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,pbus_baaw-syscon-phandle"); - if (IS_ERR(platform->pbus_baaw)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "pbus_baaw regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->pbus_baaw)); - err = -EINVAL; - goto error_exit; - } - - /* WLBT_REMAP */ - platform->wlbt_remap = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,wlbt_remap-syscon-phandle"); - if (IS_ERR(platform->wlbt_remap)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "wlbt_remap regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->wlbt_remap)); - err = -EINVAL; - goto error_exit; - } - - /* BOOT_CFG */ - platform->boot_cfg = syscon_regmap_lookup_by_phandle(platform->dev->of_node, - "samsung,boot_cfg-syscon-phandle"); - if (IS_ERR(platform->boot_cfg)) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "boot_cfg regmap lookup failed. Aborting. %ld\n", - PTR_ERR(platform->boot_cfg)); - err = -EINVAL; - goto error_exit; - } - -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER parsing */ - if (!of_property_read_u32(pdev->dev.of_node, "smapper_num_banks", &smapper_banks)) - platform_mif_parse_smapper(platform, platform->dev->of_node, smapper_banks); - -#endif -#ifdef CONFIG_SCSC_QOS - platform_mif_parse_qos(platform, platform->dev->of_node); -#endif - /* Initialize spinlock */ - spin_lock_init(&platform->mif_spinlock); - - return platform_if; - -error_exit: - devm_kfree(&pdev->dev, platform); - return NULL; -} - -void platform_mif_destroy_platform(struct platform_device *pdev, struct scsc_mif_abs *interface) -{ -} - -struct platform_device *platform_mif_get_platform_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->pdev; -} - -struct device *platform_mif_get_dev(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - BUG_ON(!interface || !platform); - - return platform->dev; -} - -/* Preserve MIF registers during suspend. - * If all users of the MIF (AP, mx140, CP, etc) release it, the registers - * will lose their values. Save the useful subset here. - * - * Assumption: the AP will not change the register values between the suspend - * and resume handlers being called! - */ -static void platform_mif_reg_save(struct platform_mif *platform) -{ - platform->mif_preserve.irq_bit_mask = __platform_mif_irq_bit_mask_read(platform); -} - -/* Restore MIF registers that may have been lost during suspend */ -static void platform_mif_reg_restore(struct platform_mif *platform) -{ - __platform_mif_irq_bit_mask_write(platform, platform->mif_preserve.irq_bit_mask); -} - -int platform_mif_suspend(struct scsc_mif_abs *interface) -{ - int r = 0; - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - - if (platform->suspend_handler) - r = platform->suspend_handler(interface, platform->suspendresume_data); - - /* Save the MIF registers. - * This must be done last as the suspend_handler may use the MIF - */ - platform_mif_reg_save(platform); - - return r; -} - -void platform_mif_resume(struct scsc_mif_abs *interface) -{ - struct platform_mif *platform = platform_mif_from_mif_abs(interface); - s32 ret; - - /* Restore the MIF registers. - * This must be done first as the resume_handler may use the MIF. - */ - platform_mif_reg_restore(platform); - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clear WLBT_ACTIVE_CLR flag\n"); - /* Clear WLBT_ACTIVE_CLR flag in WLBT_CTRL_NS */ - ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, WLBT_ACTIVE_CLR, 1); - if (ret < 0) { - SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, - "Failed to Set WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret); - } - - if (platform->resume_handler) - platform->resume_handler(interface, platform->suspendresume_data); -} - - -/* Temporary workaround to power up slave PMIC LDOs before FW APM/WLBT signalling - * is complete - */ -static void power_supplies_on(struct platform_mif *platform) -{ - struct i2c_client i2c; - - /* HACK: Note only addr field is needed by s2mpu11_write_reg() */ - i2c.addr = 0x1; - - /* The APM IPC in FW will be used instead */ - if (disable_apm_setup) { - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT LDOs firmware controlled\n"); - return; - } - - SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "WLBT LDOs on (PMIC i2c_addr = 0x%x)\n", i2c.addr); - - /* SLAVE PMIC - * echo 0x22 > /sys/kernel/debug/s2mpu11-regs/i2caddr - * echo 0xE0 > /sys/kernel/debug/s2mpu11-regs/i2cdata - * - * echo 0x23 > /sys/kernel/debug/s2mpu11-regs/i2caddr - * echo 0xE8 > /sys/kernel/debug/s2mpu11-regs/i2cdata - * - * echo 0x24 > /sys/kernel/debug/s2mpu11-regs/i2caddr - * echo 0xEC > /sys/kernel/debug/s2mpu11-regs/i2cdata - * - * echo 0x25 > /sys/kernel/debug/s2mpu11-regs/i2caddr - * echo 0xEC > /sys/kernel/debug/s2mpu11-regs/i2cdata - * - * echo 0x26 > /sys/kernel/debug/s2mpu11-regs/i2caddr - * echo 0xFC > /sys/kernel/debug/s2mpu11-regs/i2cdata - * - * echo 0x27 > /sys/kernel/debug/s2mpu11-regs/i2caddr - * echo 0xFC > /sys/kernel/debug/s2mpu11-regs/i2cdata - */ - - s2mpu11_write_reg(&i2c, 0x22, 0xe0); - s2mpu11_write_reg(&i2c, 0x23, 0xe8); - s2mpu11_write_reg(&i2c, 0x24, 0xec); - s2mpu11_write_reg(&i2c, 0x25, 0xec); - s2mpu11_write_reg(&i2c, 0x26, 0xfc); - s2mpu11_write_reg(&i2c, 0x27, 0xfc); -} diff --git a/drivers/misc/samsung/scsc/platform_mif_module.c b/drivers/misc/samsung/scsc/platform_mif_module.c deleted file mode 100644 index f66db18bec29..000000000000 --- a/drivers/misc/samsung/scsc/platform_mif_module.c +++ /dev/null @@ -1,252 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include "platform_mif_module.h" -#include "platform_mif.h" - -/* Implements */ -#include "scsc_mif_abs.h" - -/* Variables */ -struct mif_abs_node { - struct list_head list; - struct scsc_mif_abs *mif_abs; -}; - -struct mif_driver_node { - struct list_head list; - struct scsc_mif_abs_driver *driver; -}; - -struct mif_mmap_node { - struct list_head list; - struct scsc_mif_mmap_driver *driver; -}; - -static struct platform_mif_module { - struct list_head mif_abs_list; - struct list_head mif_driver_list; - struct list_head mif_mmap_list; -} mif_module = { - .mif_abs_list = LIST_HEAD_INIT(mif_module.mif_abs_list), - .mif_driver_list = LIST_HEAD_INIT(mif_module.mif_driver_list), - .mif_mmap_list = LIST_HEAD_INIT(mif_module.mif_mmap_list), -}; - -/* Private Functions */ - -static void platform_mif_module_probe_registered_clients(struct scsc_mif_abs *mif_abs) -{ - struct mif_driver_node *mif_driver_node, *next; - bool driver_registered = false; - - /* Traverse Linked List for each mif_driver node */ - list_for_each_entry_safe(mif_driver_node, next, &mif_module.mif_driver_list, list) { - mif_driver_node->driver->probe(mif_driver_node->driver, mif_abs); - driver_registered = true; - } -} - -static int platform_mif_module_probe(struct platform_device *pdev) -{ - struct mif_abs_node *mif_node; - struct scsc_mif_abs *mif_abs; - - /* TODO: ADD EARLY BOARD INITIALIZATIONS IF REQUIRED */ - /* platform_mif_init(); */ - - mif_node = kzalloc(sizeof(*mif_node), GFP_KERNEL); - if (!mif_node) - return -ENODEV; - - mif_abs = platform_mif_create(pdev); - if (!mif_abs) { - SCSC_TAG_ERR(PLAT_MIF, "Error creating platform interface\n"); - kfree(mif_node); - return -ENODEV; - } - /* Add node */ - mif_node->mif_abs = mif_abs; - list_add_tail(&mif_node->list, &mif_module.mif_abs_list); - platform_mif_module_probe_registered_clients(mif_abs); - - return 0; -} - -static int platform_mif_module_remove(struct platform_device *pdev) -{ - struct mif_abs_node *mif_node, *next; - bool match = false; - - /* Remove node */ - list_for_each_entry_safe(mif_node, next, &mif_module.mif_abs_list, list) { - if (platform_mif_get_platform_dev(mif_node->mif_abs) == pdev) { - match = true; - platform_mif_destroy_platform(pdev, mif_node->mif_abs); - list_del(&mif_node->list); - kfree(mif_node); - } - } - if (match == false) - SCSC_TAG_ERR(PLAT_MIF, "No match for given scsc_mif_abs\n"); - - return 0; -} - -static int platform_mif_module_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mif_abs_node *mif_node, *next; - int r; - - SCSC_TAG_INFO(PLAT_MIF, "\n"); - - /* Traverse mif_abs list for this platform_device to suspend */ - list_for_each_entry_safe(mif_node, next, &mif_module.mif_abs_list, list) { - if (platform_mif_get_platform_dev(mif_node->mif_abs) == pdev) { - /* Signal suspend, client can refuse */ - r = platform_mif_suspend(mif_node->mif_abs); - if (r) { - SCSC_TAG_INFO(PLAT_MIF, "%d\n", r); - return r; - } - } - } - return 0; -} - -static int platform_mif_module_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mif_abs_node *mif_node, *next; - - SCSC_TAG_INFO(PLAT_MIF, "\n"); - - /* Traverse mif_abs list for this platform_device to resume */ - list_for_each_entry_safe(mif_node, next, &mif_module.mif_abs_list, list) { - if (platform_mif_get_platform_dev(mif_node->mif_abs) == pdev) { - /* Signal resume */ - platform_mif_resume(mif_node->mif_abs); - } - } - return 0; -} - -static const struct dev_pm_ops platform_mif_pm_ops = { - .suspend = platform_mif_module_suspend, - .resume = platform_mif_module_resume, -}; - -static const struct of_device_id scsc_wifibt[] = { - { .compatible = "samsung,scsc_wifibt" }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, scsc_wifibt); - -static struct platform_driver platform_mif_driver = { - .probe = platform_mif_module_probe, - .remove = platform_mif_module_remove, - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - .pm = &platform_mif_pm_ops, - .of_match_table = of_match_ptr(scsc_wifibt), - }, -}; - -/* Choose when the driver should be probed */ -#if 1 -module_platform_driver(platform_mif_driver); -#else -static int platform_mif_init(void) -{ - SCSC_TAG_INFO(PLAT_MIF, "register platform driver\n"); - return platform_driver_register(&platform_mif_driver); -} -core_initcall(platform_mif_init); -#endif - -/* Public Functions */ -void scsc_mif_abs_register(struct scsc_mif_abs_driver *driver) -{ - struct mif_driver_node *mif_driver_node; - struct mif_abs_node *mif_node; - - /* Add node in driver linked list */ - mif_driver_node = kzalloc(sizeof(*mif_driver_node), GFP_KERNEL); - if (!mif_driver_node) - return; - - mif_driver_node->driver = driver; - list_add_tail(&mif_driver_node->list, &mif_module.mif_driver_list); - - /* Traverse Linked List for each mif_abs node */ - list_for_each_entry(mif_node, &mif_module.mif_abs_list, list) { - driver->probe(driver, mif_node->mif_abs); - } -} -EXPORT_SYMBOL(scsc_mif_abs_register); - -void scsc_mif_abs_unregister(struct scsc_mif_abs_driver *driver) -{ - struct mif_driver_node *mif_driver_node, *next; - - /* Traverse Linked List for each mif_driver node */ - list_for_each_entry_safe(mif_driver_node, next, &mif_module.mif_driver_list, list) { - if (mif_driver_node->driver == driver) { - list_del(&mif_driver_node->list); - kfree(mif_driver_node); - } - } -} -EXPORT_SYMBOL(scsc_mif_abs_unregister); - -/* Register a mmap - debug driver - for this specific transport*/ -void scsc_mif_mmap_register(struct scsc_mif_mmap_driver *mmap_driver) -{ - struct mif_mmap_node *mif_mmap_node; - struct mif_abs_node *mif_node; - - /* Add node in driver linked list */ - mif_mmap_node = kzalloc(sizeof(*mif_mmap_node), GFP_KERNEL); - if (!mif_mmap_node) - return; - - mif_mmap_node->driver = mmap_driver; - list_add_tail(&mif_mmap_node->list, &mif_module.mif_mmap_list); - - /* Traverse Linked List for each mif_abs node */ - list_for_each_entry(mif_node, &mif_module.mif_abs_list, list) { - mmap_driver->probe(mmap_driver, mif_node->mif_abs); - } -} -EXPORT_SYMBOL(scsc_mif_mmap_register); - -/* Unregister a mmap - debug driver - for this specific transport*/ -void scsc_mif_mmap_unregister(struct scsc_mif_mmap_driver *mmap_driver) -{ - struct mif_mmap_node *mif_mmap_node, *next; - - /* Traverse Linked List for each mif_driver node */ - list_for_each_entry_safe(mif_mmap_node, next, &mif_module.mif_mmap_list, list) { - if (mif_mmap_node->driver == mmap_driver) { - list_del(&mif_mmap_node->list); - kfree(mif_mmap_node); - } - } -} -EXPORT_SYMBOL(scsc_mif_mmap_unregister); - -MODULE_DESCRIPTION("SCSC Platform device Maxwell MIF abstraction"); -MODULE_AUTHOR("SCSC"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/samsung/scsc/platform_mif_module.h b/drivers/misc/samsung/scsc/platform_mif_module.h deleted file mode 100644 index 7e2007aac37e..000000000000 --- a/drivers/misc/samsung/scsc/platform_mif_module.h +++ /dev/null @@ -1,12 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __PLATFORM_MIF_MODULE_H -#define __PLATFORM_MIF_MODULE_H - -#define DRV_NAME "scsc_wlbt" - -#endif /* __PLATFORM_MIF_MODULE_H */ diff --git a/drivers/misc/samsung/scsc/scsc_app_msg.h b/drivers/misc/samsung/scsc/scsc_app_msg.h deleted file mode 100644 index af421ee8d064..000000000000 --- a/drivers/misc/samsung/scsc/scsc_app_msg.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SCSC_APP_MSG_H__ -#define __SCSC_APP_MSG_H__ - - -#define BCSP_CSTOPB_MASK 0x0001 -#define BCSP_PARENB_MASK 0x0002 -#define BCSP_PAREVEN_MASK 0x0004 -#define BCSP_CRTSCTS_MASK 0x0008 - -enum { - SCSC_APP_MSG_TYPE_APP_STARTED_REPLY = 0, - SCSC_APP_MSG_TYPE_GET_DB, - SCSC_APP_MSG_TYPE_GET_DB_REPLY, - SCSC_APP_MSG_TYPE_LD_REGISTER_LOW_RATE, - SCSC_APP_MSG_TYPE_LD_REGISTER_HIGH_RATE, - SCSC_APP_MSG_TYPE_LD_REGISTER_REPLY, - SCSC_APP_MSG_TYPE_LD_UNREGISTER, - SCSC_APP_MSG_TYPE_LD_UNREGISTER_BREAK, - SCSC_APP_MSG_TYPE_LD_UNREGISTER_REPLY, - SCSC_APP_MSG_TYPE_APP_EXIT, - SCSC_APP_MSG_TYPE_APP_EXIT_REPLY, - SCSC_APP_MSG_TYPE_SET_FAST_RATE, - SCSC_APP_MSG_TYPE_SET_FAST_RATE_REPLY, -}; - -enum { - SCSC_APP_MSG_STATUS_OK = 0, - SCSC_APP_MSG_STATUS_FAILURE, -}; - - -struct scsc_app_msg_req { - __u16 type; -}; - -struct scsc_app_msg_resp { - __u16 type; - __u16 status; - __u32 len; - __u8 data[0]; -}; - -#endif /* __SCSC_APP_MSG_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_lerna.c b/drivers/misc/samsung/scsc/scsc_lerna.c deleted file mode 100644 index 7818a4685327..000000000000 --- a/drivers/misc/samsung/scsc/scsc_lerna.c +++ /dev/null @@ -1,276 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - - -#include -#include -#include -#include -#include /* Required for copy_to_user. */ -#include -#include - -#include - -#include "mxman.h" -#include "mxmgmt_transport_format.h" /* Required for MXMGR_MESSAGE_PAYLOAD_SIZE. */ - -#define DEVICE_NAME "lerna" -#define DEVICE_CLASS "scsc_config" -#define DEVICE_COUNT (1) - -static const void *scsc_lerna_pending; -#define SCSC_LERNA_WAIT_TIMEOUT (2000) -static DECLARE_COMPLETION(scsc_lerna_wait); - -/** - * MSMGR_MESSAGE_PAYLOAD_SIZE is not a nice power of 2, so use sizeof(msmgr_message) - * just for something more aesthetically pleasing. - */ -#define SCSC_LERNA_BUFFER_SIZE (sizeof(struct mxmgr_message)) -static uint8_t scsc_lerna_request_buffer[SCSC_LERNA_BUFFER_SIZE]; -static uint8_t scsc_lerna_response_buffer[SCSC_LERNA_BUFFER_SIZE]; - -static dev_t scsc_lerna_device_id; -static struct class *scsc_lerna_class_p; -static struct device *scsc_lerna_device_p; -static struct cdev scsc_lerna_cdev; - -static int scsc_lerna_chardev_open(struct inode *inodep, struct file *filep); -static ssize_t scsc_lerna_chardev_read(struct file *filep, char *buffer, size_t len, loff_t *offset); -static ssize_t scsc_lerna_chardev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset); -static int scsc_lerna_chardev_release(struct inode *inodep, struct file *filep); - -static struct file_operations scsc_lerna_fops = { - .open = scsc_lerna_chardev_open, - .read = scsc_lerna_chardev_read, - .write = scsc_lerna_chardev_write, - .release = scsc_lerna_chardev_release, -}; - -static atomic_t scsc_lerna_atomic; - -struct scsc_lerna_cmd_header { - uint8_t magic_number; /* Set to 0x08. */ - uint8_t cid; /* Action command identifier. */ - uint16_t payload_length; /* Payload length. 0 for value query. */ - uint16_t psid; /* PSID to query. */ - uint8_t row_index; /* Row index, or 0 for non-table querying. */ - uint8_t group_index; /* Group index, or 0 for default (group not assigned). */ -}; - -static int scsc_lerna_chardev_open(struct inode *inodep, struct file *filep) -{ - (void)inodep; - (void)filep; - - if (atomic_inc_return(&scsc_lerna_atomic) > 1) { - atomic_dec(&scsc_lerna_atomic); - /* Someone already has this open. Denied. */ - SCSC_TAG_DEBUG(LERNA, "character device busy, try again later.\n"); - return -EBUSY; - } - - SCSC_TAG_DEBUG(LERNA, "opening lerna character device.\n"); - return 0; -} - -static ssize_t scsc_lerna_chardev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) -{ - const struct scsc_lerna_cmd_header *header; - unsigned long wait_result; - ssize_t read_count; - int error_count; - - (void)filep; - (void)offset; - - wait_result = wait_for_completion_timeout(&scsc_lerna_wait, msecs_to_jiffies(SCSC_LERNA_WAIT_TIMEOUT)); - if (wait_result == 0) { - SCSC_TAG_ERR(LERNA, "read timeout; firmware not responding, or read without write.\n"); - return -ETIMEDOUT; - } - - if (!scsc_lerna_pending) { - /* Pointer is NULL, indicating that a reply hasn't been sent from firmware. */ - SCSC_TAG_DEBUG(LERNA, "pending reply is null.\n"); - return -ENOMSG; - } - - header = (const struct scsc_lerna_cmd_header *)(scsc_lerna_pending); - read_count = sizeof(struct scsc_lerna_cmd_header) + header->payload_length; - - /* Make sure there's enough space to read out the buffer. */ - if (len < read_count) { - SCSC_TAG_ERR(LERNA, "insufficient buffer space supplied for read.\n"); - return -ENOBUFS; - } - - error_count = copy_to_user(buffer, scsc_lerna_pending, read_count); - - if (error_count) { - SCSC_TAG_ERR(LERNA, "could not read from lerna character device.\n"); - return -EFAULT; - } - - SCSC_TAG_DEBUG(LERNA, "read buffer of size: %lu\n", read_count); - /* Value was read out, and is no longer considered valid. Need to write before another read. */ - scsc_lerna_pending = NULL; - return read_count; -} - -static ssize_t scsc_lerna_chardev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) -{ - SCSC_TAG_DEBUG(LERNA, "writing buffer of size: %lu\n", len); - /* At a minimum, any request (read or write) must include a command header. */ - if (len >= sizeof(struct scsc_lerna_cmd_header)) { - /* Header at least fits, but maybe a write value wants more... */ - if (len <= SCSC_LERNA_BUFFER_SIZE) { - copy_from_user(scsc_lerna_request_buffer, buffer, len); - mxman_lerna_send(NULL, scsc_lerna_request_buffer, len); - } else { - /* Message size too long, don't write anything. */ - return -EMSGSIZE; - } - } else { - return -EBADR; - } - - return len; -} - -static int scsc_lerna_chardev_release(struct inode *inodep, struct file *filep) -{ - (void)inodep; - (void)filep; - if (atomic_read(&scsc_lerna_atomic) == 0) { - SCSC_TAG_ALERT(LERNA, "character device release without open.\n"); - } else { - /* Done with the character device, release the lock on it. */ - atomic_dec(&scsc_lerna_atomic); - } - - SCSC_TAG_DEBUG(LERNA, "lerna character device closed.\n"); - return 0; -} - - -int scsc_lerna_init(void) -{ - int result; - - /** - * Reset important globals to some kind of sane value. This should be done - * whenever the module is loaded explicitly to be sure global values haven't - * been previously trashed. - */ - scsc_lerna_device_id = 0; - scsc_lerna_class_p = NULL; - scsc_lerna_device_p = NULL; - - /* Make sure to initialise the atomic used to lock char device access. */ - atomic_set(&scsc_lerna_atomic, 0); - - /** - * Allocate device id(s) for the character device. Use alloc_register_chrdev - * because this is the new way of doing things, and it will dynamically allocate - * a major number. Returns non-zero on failure. - */ - result = alloc_chrdev_region(&scsc_lerna_device_id, 0, DEVICE_COUNT, DEVICE_NAME); - if (result) { - /* Failure to register char dev, auto fail to initialise module. */ - SCSC_TAG_ALERT(LERNA, "lerna failed to register character device.\n"); - return result; - } - - scsc_lerna_class_p = class_create(THIS_MODULE, DEVICE_CLASS); - if (IS_ERR(scsc_lerna_class_p)) { - /* Could not create class, failure, remember to unregister device id(s). */ - unregister_chrdev_region(scsc_lerna_device_id, DEVICE_COUNT); - SCSC_TAG_ALERT(LERNA, "lerna failed to create character class.\n"); - return PTR_ERR(scsc_lerna_class_p); - } - - scsc_lerna_device_p = device_create(scsc_lerna_class_p, NULL, scsc_lerna_device_id, NULL, DEVICE_NAME); - if (IS_ERR(scsc_lerna_device_p)) { - class_destroy(scsc_lerna_class_p); - unregister_chrdev_region(scsc_lerna_device_id, DEVICE_COUNT); - SCSC_TAG_ALERT(LERNA, "lerna failed to create character device.\n"); - return PTR_ERR(scsc_lerna_device_p); - } - - /** - * At this point, the device is registered, along with class definition. The character device - * itself can now be initialised to provide the kernel with callback information for various - * actions taken on the device. - */ - cdev_init(&scsc_lerna_cdev, &scsc_lerna_fops); - scsc_lerna_cdev.owner = THIS_MODULE; - - result = cdev_add(&scsc_lerna_cdev, scsc_lerna_device_id, DEVICE_COUNT); - if (result) { - /* Failure to add character device to file system. */ - cdev_del(&scsc_lerna_cdev); - class_destroy(scsc_lerna_class_p); - unregister_chrdev_region(scsc_lerna_device_id, DEVICE_COUNT); - SCSC_TAG_ALERT(LERNA, "lerna failed to add character device.\n"); - return result; - } - /* At this point, the cdev is live and can be used. */ - - SCSC_TAG_INFO(LERNA, "lerna intialisation complete.\n"); - return 0; /* 0 for module loaded, non-zero for module load failure. */ -} - -void scsc_lerna_deinit(void) -{ - /* Character device needs deleting. */ - cdev_del(&scsc_lerna_cdev); - - /* Destroy device. */ - device_destroy(scsc_lerna_class_p, scsc_lerna_device_id); - - /* Unregister the device class. Not sure if this means that a register earlier is required. */ - class_unregister(scsc_lerna_class_p); - - /* Destroy created class. Be careful of the order this is called in. */ - class_destroy(scsc_lerna_class_p); - - /** - * Don't forget to unregister device id(s). Major number is dynamically allocated, - * so the base id is remembered and passed along to the unregister here. - */ - unregister_chrdev_region(scsc_lerna_device_id, DEVICE_COUNT); - - SCSC_TAG_INFO(LERNA, "lerna shutdown complete.\n"); -} - -void scsc_lerna_response(const void *message) -{ - /** - * Buffer the response from the firmware so that future messages from firmware - * don't overwrite this accidentally. This means async messages are allowed while - * waiting for the character device read from userspace, without impacting lerna's - * request/response communications. - */ - const struct scsc_lerna_cmd_header *header; - ssize_t read_count; - - if (message != NULL) { - header = (const struct scsc_lerna_cmd_header *)(message); - read_count = sizeof(struct scsc_lerna_cmd_header) + header->payload_length; - - if (read_count <= SCSC_LERNA_BUFFER_SIZE) { - memcpy(scsc_lerna_response_buffer, message, read_count); - scsc_lerna_pending = scsc_lerna_response_buffer; - } else { - SCSC_TAG_DEBUG(LERNA, "readout too large for response buffering.\n"); - /* No response possible, let the userspace application deal with it. */ - scsc_lerna_pending = NULL; - } - } - complete(&scsc_lerna_wait); -} diff --git a/drivers/misc/samsung/scsc/scsc_lerna.h b/drivers/misc/samsung/scsc/scsc_lerna.h deleted file mode 100644 index 98fd963888cf..000000000000 --- a/drivers/misc/samsung/scsc/scsc_lerna.h +++ /dev/null @@ -1,16 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef _SCSC_LERNA_H -#define _SCSC_LERNA_H - -int scsc_lerna_init(void); - -void scsc_lerna_deinit(void); - -void scsc_lerna_response(const void *message); - -#endif /* _SCSC_LERNA_H */ diff --git a/drivers/misc/samsung/scsc/scsc_log_collector.c b/drivers/misc/samsung/scsc/scsc_log_collector.c deleted file mode 100644 index 818d09e32854..000000000000 --- a/drivers/misc/samsung/scsc/scsc_log_collector.c +++ /dev/null @@ -1,538 +0,0 @@ -/******************************************************************************** - * - * Copyright (c) 2016 - 2019 Samsung Electronics Co., Ltd. All rights reserved. - * - ********************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "scsc_log_collector_proc.h" -#include "scsc_log_collector_mmap.h" -#include -#include "mxlogger.h" - -#ifdef CONFIG_SCSC_WLBTD -#include "scsc_wlbtd.h" -#endif - -#define SCSC_NUM_CHUNKS_SUPPORTED 13 - -#define TO_RAM 0 -#define TO_FILE 1 -/* Add-remove supported chunks on this kernel */ -static u8 chunk_supported_sbl[SCSC_NUM_CHUNKS_SUPPORTED] = { - SCSC_LOG_CHUNK_SYNC, - SCSC_LOG_CHUNK_IMP, - SCSC_LOG_CHUNK_MXL, - SCSC_LOG_CHUNK_UDI, - SCSC_LOG_CHUNK_BT_HCF, - SCSC_LOG_CHUNK_WLAN_HCF, - SCSC_LOG_CHUNK_HIP4_SAMPLER, - SCSC_LOG_RESERVED_COMMON, - SCSC_LOG_RESERVED_BT, - SCSC_LOG_RESERVED_WLAN, - SCSC_LOG_RESERVED_RADIO, - SCSC_LOG_MINIMOREDUMP, - SCSC_LOG_CHUNK_LOGRING, -}; - -static int scsc_log_collector_collect(enum scsc_log_reason reason, u16 reason_code); - -static atomic_t in_collection; - -/* Collect logs in an intermediate buffer to be collected at later time (mmap or wq) */ -static bool collect_to_ram = true; -module_param(collect_to_ram, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(collect_to_ram, "Collect buffer in ram"); - -static char collection_dir_buf[256] = "/data/vendor/log/wifi"; -module_param_string(collection_target_directory, collection_dir_buf, sizeof(collection_dir_buf), S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(collection_target_directory, "Specify collection target directory"); - -static bool sable_collection_off; -static int sable_collection_off_set_param_cb(const char *val, - const struct kernel_param *kp) -{ - bool nval; - - if (!val || strtobool(val, &nval)) - return -EINVAL; - - if (sable_collection_off ^ nval) { - sable_collection_off = nval; - mxlogger_set_enabled_status(!sable_collection_off); - pr_info("Sable Log Collection is now %sABLED.\n", - sable_collection_off ? "DIS" : "EN"); - } - return 0; -} - -/** - * As described in struct kernel_param+ops the _get method: - * -> returns length written or -errno. Buffer is 4k (ie. be short!) - */ -static int sable_collection_off_get_param_cb(char *buffer, - const struct kernel_param *kp) -{ - return sprintf(buffer, "%c", sable_collection_off ? 'Y' : 'N'); -} - -static struct kernel_param_ops sable_collection_off_ops = { - .set = sable_collection_off_set_param_cb, - .get = sable_collection_off_get_param_cb, -}; -module_param_cb(sable_collection_off, &sable_collection_off_ops, NULL, 0644); -MODULE_PARM_DESC(sable_collection_off, "Disable SABLE Log Collection. This will inhibit also MXLOGGER"); - -struct scsc_log_client { - struct list_head list; - struct scsc_log_collector_client *collect_client; -}; -static struct scsc_log_collector_list { struct list_head list; } scsc_log_collector_list = { - .list = LIST_HEAD_INIT(scsc_log_collector_list.list) -}; - -struct scsc_log_status { - struct file *fp; - loff_t pos; - bool in_collection; - char fapi_ver[SCSC_LOG_FAPI_VERSION_SIZE]; - - unsigned char *buf; - struct workqueue_struct *collection_workq; - struct work_struct collect_work; - enum scsc_log_reason collect_reason; - u16 reason_code; - struct mutex collection_serial; - bool observer_present; -} log_status; - -static DEFINE_MUTEX(log_mutex); - -static void collection_worker(struct work_struct *work) -{ - struct scsc_log_status *ls; - - ls = container_of(work, struct scsc_log_status, collect_work); - /* ls cannot be NULL due to pointer arithmetic */ - - pr_info("SCSC running scheduled Log Collection - collect reason:%d reason code:%d\n", - ls->collect_reason, ls->reason_code); - scsc_log_collector_collect(ls->collect_reason, ls->reason_code); - atomic_set(&in_collection, 0); -} - -/* Module init */ -int __init scsc_log_collector(void) -{ - pr_info("Log Collector Init\n"); - - log_status.in_collection = false; - log_status.collection_workq = create_workqueue("log_collector"); - if (log_status.collection_workq) - INIT_WORK(&log_status.collect_work, collection_worker); - /* Update mxlogger status on init.*/ - pr_info("Sable Log Collection is now %sABLED.\n", - sable_collection_off ? "DIS" : "EN"); - mxlogger_set_enabled_status(!sable_collection_off); - - /* Create the buffer on the constructor */ - log_status.buf = vzalloc(SCSC_LOG_COLLECT_MAX_SIZE); - if (IS_ERR_OR_NULL(log_status.buf)) { - pr_err("open allocating memmory err = %ld\n", PTR_ERR(log_status.buf)); - log_status.buf = NULL; - } - - mutex_init(&log_status.collection_serial); - - scsc_log_collect_proc_create(); - scsc_log_collector_mmap_create(); - return 0; -} - -void __exit scsc_log_collector_exit(void) -{ - if (log_status.buf) - vfree(log_status.buf); - - scsc_log_collect_proc_remove(); - if (log_status.collection_workq) { - flush_workqueue(log_status.collection_workq); - destroy_workqueue(log_status.collection_workq); - log_status.collection_workq = NULL; - } - - pr_info("Log Collect Unloaded\n"); -} - -module_init(scsc_log_collector); -module_exit(scsc_log_collector_exit); - -static bool scsc_is_chunk_supported(u8 type) -{ - u8 i; - - for (i = 0; i < SCSC_NUM_CHUNKS_SUPPORTED; i++) { - if (type == chunk_supported_sbl[i]) - return true; - } - - return false; -} - -static int scsc_log_collector_compare(void *priv, struct list_head *A, struct list_head *B) -{ - struct scsc_log_client *a = list_entry(A, typeof(*a), list); - struct scsc_log_client *b = list_entry(B, typeof(*b), list); - - if (a->collect_client->type < b->collect_client->type) - return -1; - else - return 1; -} - -int scsc_log_collector_register_client(struct scsc_log_collector_client *collect_client) -{ - struct scsc_log_client *lc; - - if (!scsc_is_chunk_supported(collect_client->type)) { - pr_info("Type not supported: %d\n", collect_client->type); - return -EIO; - } - - mutex_lock(&log_mutex); - lc = kzalloc(sizeof(*lc), GFP_KERNEL); - if (!lc) { - mutex_unlock(&log_mutex); - return -ENOMEM; - } - - lc->collect_client = collect_client; - list_add_tail(&lc->list, &scsc_log_collector_list.list); - - /* Sort the list */ - list_sort(NULL, &scsc_log_collector_list.list, scsc_log_collector_compare); - - pr_info("Registered client: %s\n", collect_client->name); - mutex_unlock(&log_mutex); - return 0; -} -EXPORT_SYMBOL(scsc_log_collector_register_client); - -int scsc_log_collector_unregister_client(struct scsc_log_collector_client *collect_client) -{ - struct scsc_log_client *lc, *next; - bool match = false; - - /* block any attempt of unregistering while a collection is in progres */ - mutex_lock(&log_mutex); - list_for_each_entry_safe(lc, next, &scsc_log_collector_list.list, list) { - if (lc->collect_client == collect_client) { - match = true; - list_del(&lc->list); - kfree(lc); - } - } - - if (match == false) - pr_err("FATAL, no match for given scsc_log_collector_client\n"); - - pr_info("Unregistered client: %s\n", collect_client->name); - mutex_unlock(&log_mutex); - - return 0; -} -EXPORT_SYMBOL(scsc_log_collector_unregister_client); - - -unsigned char *scsc_log_collector_get_buffer(void) -{ - return log_status.buf; -} - -static int __scsc_log_collector_write_to_ram(char __user *buf, size_t count, u8 align) -{ - if (!log_status.in_collection || !log_status.buf) - return -EIO; - - if (log_status.pos + count > SCSC_LOG_COLLECT_MAX_SIZE) { - pr_err("Write will exceed SCSC_LOG_COLLECT_MAX_SIZE. Abort write\n"); - return -ENOMEM; - } - - log_status.pos = (log_status.pos + align - 1) & ~(align - 1); - /* Write buf to RAM */ - memcpy(log_status.buf + log_status.pos, buf, count); - - log_status.pos += count; - - return 0; -} - -static int __scsc_log_collector_write_to_file(char __user *buf, size_t count, u8 align) -{ - int ret = 0; - - if (!log_status.in_collection) - return -EIO; - - if (log_status.pos + count > SCSC_LOG_COLLECT_MAX_SIZE) { - pr_err("Write will exceed SCSC_LOG_COLLECT_MAX_SIZE. Abort write\n"); - return -ENOMEM; - } - - log_status.pos = (log_status.pos + align - 1) & ~(align - 1); - /* Write buf to file */ - ret = vfs_write(log_status.fp, buf, count, &log_status.pos); - if (ret < 0) { - pr_err("write file error, err = %d\n", ret); - return ret; - } - return 0; -} - -int scsc_log_collector_write(char __user *buf, size_t count, u8 align) -{ - if (collect_to_ram) - return __scsc_log_collector_write_to_ram(buf, count, align); - else - return __scsc_log_collector_write_to_file(buf, count, align); -} -EXPORT_SYMBOL(scsc_log_collector_write); - -#define align_chunk(ppos) (((ppos) + (SCSC_LOG_CHUNK_ALIGN - 1)) & \ - ~(SCSC_LOG_CHUNK_ALIGN - 1)) - -static int __scsc_log_collector_collect(enum scsc_log_reason reason, u16 reason_code, u8 buffer) -{ - struct scsc_log_client *lc, *next; - mm_segment_t old_fs; - char memdump_path[128]; - int ret = 0; - char version_fw[SCSC_LOG_FW_VERSION_SIZE] = {0}; - char version_host[SCSC_LOG_HOST_VERSION_SIZE] = {0}; - u32 mem_pos, temp_pos, chunk_size; - ktime_t start; - u8 num_chunks = 0; - u16 first_chunk_pos = SCSC_LOG_OFFSET_FIRST_CHUNK; - struct scsc_log_sbl_header sbl_header; - struct scsc_log_chunk_header chk_header; - u8 j; - bool sbl_is_valid = false; - - mutex_lock(&log_mutex); - - pr_info("Log collection triggered %s reason_code 0x%x\n", - scsc_get_trigger_str((int)reason), reason_code); - - start = ktime_get(); - - if (buffer == TO_FILE) { - snprintf(memdump_path, sizeof(memdump_path), "%s/%s.sbl", - collection_dir_buf, scsc_get_trigger_str((int)reason)); - - /* change to KERNEL_DS address limit */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - - log_status.fp = filp_open(memdump_path, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0664); - if (IS_ERR(log_status.fp)) { - pr_err("open file error, err = %ld\n", PTR_ERR(log_status.fp)); - mutex_unlock(&log_mutex); - return PTR_ERR(log_status.fp); - } - } else if (!log_status.buf) { - pr_err("RAM buffer not created. Aborting dump\n"); - mutex_unlock(&log_mutex); - return -ENOMEM; - } - - log_status.in_collection = true; - /* Position index to start of the first chunk */ - log_status.pos = SCSC_LOG_OFFSET_FIRST_CHUNK; - - /* Call client init callbacks if any */ - list_for_each_entry_safe(lc, next, &scsc_log_collector_list.list, list) { - if (lc->collect_client && lc->collect_client->collect_init) - lc->collect_client->collect_init(lc->collect_client); - } - /* Traverse all the clients from the list.. Those would start calling scsc_log_collector_write!!*/ - /* Create chunk */ - list_for_each_entry_safe(lc, next, &scsc_log_collector_list.list, list) { - if (lc->collect_client) { - num_chunks++; - /* Create Chunk */ - /* Store current post */ - temp_pos = log_status.pos; - /* Make room for chunck header */ - log_status.pos += SCSC_CHUNK_HEADER_SIZE; - /* Execute clients callbacks */ - if (lc->collect_client->collect(lc->collect_client, 0)) - goto exit; - /* Write chunk headers */ - /* Align log_status.pos */ - mem_pos = log_status.pos = align_chunk(log_status.pos); - chunk_size = log_status.pos - temp_pos - SCSC_CHUNK_HEADER_SIZE; - /* rewind pos */ - log_status.pos = temp_pos; - /* Write chunk header */ - memcpy(chk_header.magic, "CHK", 3); - chk_header.type = (char)lc->collect_client->type; - chk_header.chunk_size = chunk_size; - scsc_log_collector_write((char *)&chk_header, sizeof(struct scsc_log_chunk_header), 1); - /* restore position for next chunk */ - log_status.pos = mem_pos; - } - } - /* Callbacks to clients have finished at this point. */ - /* Write file header */ - /* Move position to start of file */ - log_status.pos = 0; - /* Write header */ - memset(&sbl_header, 0, sizeof(sbl_header)); - memcpy(sbl_header.magic, "SCSC", 4); - sbl_header.version_major = SCSC_LOG_HEADER_VERSION_MAJOR; - sbl_header.version_minor = SCSC_LOG_HEADER_VERSION_MINOR; - sbl_header.num_chunks = num_chunks; - sbl_header.trigger = reason; - sbl_header.reason_code = reason_code; - sbl_header.observer = log_status.observer_present; - sbl_header.offset_data = first_chunk_pos; - mxman_get_fw_version(version_fw, SCSC_LOG_FW_VERSION_SIZE); - memcpy(sbl_header.fw_version, version_fw, SCSC_LOG_FW_VERSION_SIZE); - mxman_get_driver_version(version_host, SCSC_LOG_HOST_VERSION_SIZE); - memcpy(sbl_header.host_version, version_host, SCSC_LOG_HOST_VERSION_SIZE); - memcpy(sbl_header.fapi_version, log_status.fapi_ver, SCSC_LOG_FAPI_VERSION_SIZE); - - memset(sbl_header.supported_chunks, SCSC_LOG_CHUNK_INVALID, SCSC_SUPPORTED_CHUNKS_HEADER); - for (j = 0; j < SCSC_NUM_CHUNKS_SUPPORTED; j++) - sbl_header.supported_chunks[j] = chunk_supported_sbl[j]; - - scsc_log_collector_write((char *)&sbl_header, sizeof(struct scsc_log_sbl_header), 1); - - if (buffer == TO_FILE) { - /* Sync file from filesystem to physical media */ - ret = vfs_fsync(log_status.fp, 0); - if (ret < 0) { - pr_err("sync file error, error = %d\n", ret); - goto exit; - } - } - - sbl_is_valid = true; -exit: - if (buffer == TO_FILE) { - /* close file before return */ - if (!IS_ERR(log_status.fp)) - filp_close(log_status.fp, current->files); - - /* restore previous address limit */ - set_fs(old_fs); - } - - log_status.in_collection = false; - - list_for_each_entry_safe(lc, next, &scsc_log_collector_list.list, list) { - if (lc->collect_client && lc->collect_client->collect_end) - lc->collect_client->collect_end(lc->collect_client); - } - - pr_info("Calling sable collection\n"); - -#ifdef CONFIG_SCSC_WLBTD - if (sbl_is_valid) - call_wlbtd_sable((u8)reason, reason_code); -#endif - pr_info("Log collection end. Took: %lld\n", ktime_to_ns(ktime_sub(ktime_get(), start))); - - mutex_unlock(&log_mutex); - - return ret; -} - -static int scsc_log_collector_collect(enum scsc_log_reason reason, u16 reason_code) -{ - int ret = -1; - - if (sable_collection_off) { - pr_info("Sable Log collection is currently DISABLED (sable_collection_off=Y).\n"); - pr_info("Ignoring incoming Sable Collection request with Reason=%d.\n", reason); - return ret; - } - - if (collect_to_ram) - ret = __scsc_log_collector_collect(reason, reason_code, TO_RAM); - else - ret = __scsc_log_collector_collect(reason, reason_code, TO_FILE); - - return ret; -} - -void scsc_log_collector_schedule_collection(enum scsc_log_reason reason, u16 reason_code) -{ - - if (log_status.collection_workq) { - mutex_lock(&log_status.collection_serial); - pr_info("Log collection Schedule"); - - /* Serialize with previous work if the reason is a FW panic */ - if (reason == SCSC_LOG_FW_PANIC) - flush_work(&log_status.collect_work); - else if (atomic_read(&in_collection)) { - pr_info("Log collection %s reason_code 0x%x rejected. Collection already scheduled\n", - scsc_get_trigger_str((int)reason), reason_code); - mutex_unlock(&log_status.collection_serial); - return; - } - log_status.collect_reason = reason; - log_status.reason_code = reason_code; - if (!queue_work(log_status.collection_workq, &log_status.collect_work)) { - pr_info("Log collection %s reason_code 0x%x queue_work error\n", - scsc_get_trigger_str((int)reason), reason_code); - mutex_unlock(&log_status.collection_serial); - return; - } - atomic_set(&in_collection, 1); - pr_info("Log collection Scheduled"); - - /* If dumping a FW panic (i.e. collecting a moredump), we need - * to wait for the collection to finish before returning. - */ - if (reason == SCSC_LOG_FW_PANIC) - flush_work(&log_status.collect_work); - - mutex_unlock(&log_status.collection_serial); - - } else { - pr_err("Log Collection Workqueue NOT available...aborting scheduled collection.\n"); - } -} -EXPORT_SYMBOL(scsc_log_collector_schedule_collection); - -void scsc_log_collector_write_fapi(char __user *buf, size_t len) -{ - if (len > SCSC_LOG_FAPI_VERSION_SIZE) - len = SCSC_LOG_FAPI_VERSION_SIZE; - memcpy(log_status.fapi_ver, buf, len); -} -EXPORT_SYMBOL(scsc_log_collector_write_fapi); - -void scsc_log_collector_is_observer(bool observer) -{ - log_status.observer_present = observer; -} -EXPORT_SYMBOL(scsc_log_collector_is_observer); - -MODULE_DESCRIPTION("SCSC Log collector"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/misc/samsung/scsc/scsc_log_collector_mmap.c b/drivers/misc/samsung/scsc/scsc_log_collector_mmap.c deleted file mode 100644 index c255807fa51b..000000000000 --- a/drivers/misc/samsung/scsc/scsc_log_collector_mmap.c +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include "scsc_log_collector_mmap.h" - -#define DEVICE_NAME "scsc_log_collector" -#define N_MINORS 1 - -struct class *scsc_log_collector_class; -struct cdev scsc_log_collector_dev[N_MINORS]; -dev_t dev_num; - -static int scsc_log_collector_mmap_open(struct inode *inode, struct file *filp) -{ - pr_info("scsc_log_collector_mmap_open\n"); - return 0; -} - -static int scsc_log_collector_release(struct inode *inode, struct file *filp) -{ - pr_info("scsc_log_collector_release\n"); - return 0; -} - -static int scsc_log_collector_mmap(struct file *filp, struct vm_area_struct *vma) -{ - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - unsigned long page, pos; - unsigned char *buf; - - if (size > SCSC_LOG_COLLECT_MAX_SIZE) - return -EINVAL; - if (offset > SCSC_LOG_COLLECT_MAX_SIZE - size) - return -EINVAL; - - buf = scsc_log_collector_get_buffer(); - if (!buf) { - pr_err("No buffer mapped\n"); - return -ENOMEM; - } - - pos = (unsigned long)buf + offset; - - pr_info("scsc_log_collector_mmap size:%lu offset %ld\n", size, offset); - - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -static const struct file_operations scsc_log_collector_mmap_fops = { - .owner = THIS_MODULE, - .open = scsc_log_collector_mmap_open, - .mmap = scsc_log_collector_mmap, - .release = scsc_log_collector_release, -}; - -int scsc_log_collector_mmap_create(void) -{ - struct device *dev; - int i; - int ret; - dev_t curr_dev; - - /* Request the kernel for N_MINOR devices */ - ret = alloc_chrdev_region(&dev_num, 0, N_MINORS, "scsc_log_collector"); - if (ret) { - pr_err("alloc_chrdev_region failed"); - goto error; - } - - /* Create a class : appears at /sys/class */ - scsc_log_collector_class = class_create(THIS_MODULE, "scsc_log_collector_class"); - if (IS_ERR(scsc_log_collector_class)) { - ret = PTR_ERR(scsc_log_collector_class); - goto error_class; - } - - /* Initialize and create each of the device(cdev) */ - for (i = 0; i < N_MINORS; i++) { - /* Associate the cdev with a set of file_operations */ - cdev_init(&scsc_log_collector_dev[i], &scsc_log_collector_mmap_fops); - - ret = cdev_add(&scsc_log_collector_dev[i], dev_num, 1); - if (ret) - pr_err("cdev_add failed"); - - scsc_log_collector_dev[i].owner = THIS_MODULE; - /* Build up the current device number. To be used further */ - dev = device_create(scsc_log_collector_class, NULL, dev_num, NULL, "scsc_log_collector_%d", i); - if (IS_ERR(dev)) { - pr_err("device_create failed"); - ret = PTR_ERR(dev); - cdev_del(&scsc_log_collector_dev[i]); - continue; - } - curr_dev = MKDEV(MAJOR(dev_num), MINOR(dev_num) + i); - } - - return 0; - -error_class: - unregister_chrdev_region(dev_num, N_MINORS); -error: - return 0; -} - -int scsc_log_collector_mmap_destroy(void) -{ - int i; - - device_destroy(scsc_log_collector_class, dev_num); - for (i = 0; i < N_MINORS; i++) - cdev_del(&scsc_log_collector_dev[i]); - class_destroy(scsc_log_collector_class); - unregister_chrdev_region(dev_num, N_MINORS); - return 0; -} diff --git a/drivers/misc/samsung/scsc/scsc_log_collector_mmap.h b/drivers/misc/samsung/scsc/scsc_log_collector_mmap.h deleted file mode 100644 index df1eefeb308a..000000000000 --- a/drivers/misc/samsung/scsc/scsc_log_collector_mmap.h +++ /dev/null @@ -1,12 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef SCSC_LOG_COLLECT_MMAP_H -#define SCSC_LOG_COLLECT_MMAP_H - -int scsc_log_collector_mmap_create(void); -int scsc_log_collector_mmap_destroy(void); -#endif /* SCSC_log_collect_MMAP_H */ diff --git a/drivers/misc/samsung/scsc/scsc_log_collector_proc.c b/drivers/misc/samsung/scsc/scsc_log_collector_proc.c deleted file mode 100644 index 9523eb22554c..000000000000 --- a/drivers/misc/samsung/scsc/scsc_log_collector_proc.c +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include "scsc_log_collector_proc.h" - -static struct proc_dir_entry *procfs_dir; - -static int log_collect_procfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = LOG_COLLECT_PDE_DATA(inode); - return 0; -} - -LOG_COLLECT_PROCFS_RW_FILE_OPS(trigger_collection); - -static ssize_t log_collect_procfs_trigger_collection_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - /* Avoid unused parameter error */ - (void)file; - - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "OK"); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t log_collect_procfs_trigger_collection_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - char val; - - /* check that only one digit is passed */ - if (count != 2) - pr_err("%s: Incorrect argument length\n", __func__); - - if (copy_from_user(&val, user_buf, 1)) - return -EFAULT; - - if (val == '1') { - pr_info("%s: Userland has triggered log collection\n", __func__); - scsc_log_collector_schedule_collection(SCSC_LOG_USER, SCSC_LOG_USER_REASON_PROC); - } else if (val == '2') { - pr_info("%s: Dumpstate/dumpsys has triggered log collection\n", __func__); - scsc_log_collector_schedule_collection(SCSC_LOG_DUMPSTATE, SCSC_LOG_DUMPSTATE_REASON); - } else { - pr_err("%s: Incorrect argument\n", __func__); - } - return count; -} - -static const char *procdir = "driver/scsc_log_collect"; - -#define LOG_COLLECT_DIRLEN 128 - -int scsc_log_collect_proc_create(void) -{ - char dir[LOG_COLLECT_DIRLEN]; - struct proc_dir_entry *parent; - - (void)snprintf(dir, sizeof(dir), "%s", procdir); - parent = proc_mkdir(dir, NULL); - if (parent) { -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = NULL; -#endif - procfs_dir = parent; - - LOG_COLLECT_PROCFS_ADD_FILE(NULL, trigger_collection, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - } else { - pr_err("failed to create /proc dir\n"); - return -EINVAL; - } - - return 0; -} - -void scsc_log_collect_proc_remove(void) -{ - if (procfs_dir) { - char dir[LOG_COLLECT_DIRLEN]; - - LOG_COLLECT_PROCFS_REMOVE_FILE(trigger_collection, procfs_dir); - (void)snprintf(dir, sizeof(dir), "%s", procdir); - remove_proc_entry(dir, NULL); - procfs_dir = NULL; - } -} diff --git a/drivers/misc/samsung/scsc/scsc_log_collector_proc.h b/drivers/misc/samsung/scsc/scsc_log_collector_proc.h deleted file mode 100644 index 22321edb7fc2..000000000000 --- a/drivers/misc/samsung/scsc/scsc_log_collector_proc.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* - * Chip Manager /proc interface - */ -#include -#include -#include - -#ifndef SCSC_LOG_COLLECT_PROC_H -#define SCSC_LOG_COLLECT_PROC_H - -#ifndef AID_MX -#define AID_MX 0444 -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define LOG_COLLECT_PDE_DATA(inode) PDE_DATA(inode) -#else -#define LOG_COLLECT_PDE_DATA(inode) (PDE(inode)->data) -#endif - -#define LOG_COLLECT_PROCFS_RW_FILE_OPS(name) \ - static ssize_t log_collect_procfs_ ## name ## _write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); \ - static ssize_t log_collect_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations log_collect_procfs_ ## name ## _fops = { \ - .read = log_collect_procfs_ ## name ## _read, \ - .write = log_collect_procfs_ ## name ## _write, \ - .open = log_collect_procfs_open_file_generic, \ - .llseek = generic_file_llseek \ - } - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define LOG_COLLECT_PROCFS_SET_UID_GID(_entry) \ - do { \ - kuid_t proc_kuid = KUIDT_INIT(AID_MX); \ - kgid_t proc_kgid = KGIDT_INIT(AID_MX); \ - proc_set_user(_entry, proc_kuid, proc_kgid); \ - } while (0) -#else -#define LOG_COLLECT_PROCFS_SET_UID_GID(entry) \ - do { \ - (entry)->uid = AID_MX; \ - (entry)->gid = AID_MX; \ - } while (0) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define LOG_COLLECT_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry = proc_create_data(# name, mode, parent, &log_collect_procfs_ ## name ## _fops, _sdev); \ - LOG_COLLECT_PROCFS_SET_UID_GID(entry); \ - } while (0) -#else -#define LOG_COLLECT_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = create_proc_entry(# name, mode, parent); \ - if (entry) { \ - entry->proc_fops = &log_collect_procfs_ ## name ## _fops; \ - entry->data = _sdev; \ - LOG_COLLECT_PROCFS_SET_UID_GID(entry); \ - } \ - } while (0) -#endif - -#define LOG_COLLECT_PROCFS_REMOVE_FILE(name, parent) remove_proc_entry(# name, parent) - -int scsc_log_collect_proc_create(void); -void scsc_log_collect_proc_remove(void); - -#endif /* SCSC_log_collect__PROC_H */ diff --git a/drivers/misc/samsung/scsc/scsc_logring_common.h b/drivers/misc/samsung/scsc/scsc_logring_common.h deleted file mode 100644 index 488e532aa50a..000000000000 --- a/drivers/misc/samsung/scsc/scsc_logring_common.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#ifndef __SCSC_LOGRING_COMMON_H__ -#define __SCSC_LOGRING_COMMON_H__ - -enum scsc_log_level { - SCSC_MIN_DBG = 0, - SCSC_EMERG = SCSC_MIN_DBG, - SCSC_ALERT, - SCSC_CRIT, - SCSC_ERR, - SCSC_WARNING, - SCSC_NOTICE, - SCSC_INFO, - SCSC_DEBUG, - SCSC_DBG1 = SCSC_DEBUG, /* 7 */ - SCSC_DBG2, - SCSC_DBG3, - SCSC_DBG4, /* 10 */ - SCSC_FULL_DEBUG -}; - -#define SCSC_SOH 0x01 -#define DEFAULT_DBGLEVEL SCSC_INFO /* KERN_INFO */ -#define DEFAULT_DROPLEVEL SCSC_FULL_DEBUG /* DBG4 + 1 */ -#define DEFAULT_ALL_DISABLED -1 -#define DEFAULT_DROP_ALL 0 -#define DEFAULT_REDIRECT_DROPLVL SCSC_DEBUG -#define DEFAULT_NO_REDIRECT 0 -#define DEFAULT_TBUF_SZ 4096 - -/** - * Nested macros needed to force expansion of 'defval' - * before stringification takes place. Allows for ONE level - * of indirection specifying params. - */ -#define SCSC_MODPARAM_DESC(kparam, descr, eff, defval) \ - __SCSC_MODPARAM_DESC(kparam, descr, eff, defval) - -#define __SCSC_MODPARAM_DESC(kparam, descr, eff, defval) \ - MODULE_PARM_DESC(kparam, " "descr " Effective @"eff " default=" # defval ".") - - -#endif /* __SCSC_LOGRING_COMMON_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_logring_debugfs.c b/drivers/misc/samsung/scsc/scsc_logring_debugfs.c deleted file mode 100644 index 18493f0297d6..000000000000 --- a/drivers/misc/samsung/scsc/scsc_logring_debugfs.c +++ /dev/null @@ -1,706 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ - -#include -#include "scsc_logring_main.h" -#include "scsc_logring_debugfs.h" - -static int scsc_max_records_per_read = SCSC_DEFAULT_MAX_RECORDS_PER_READ; -module_param(scsc_max_records_per_read, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(scsc_max_records_per_read, - "Number of records a reader can try to get in a shot. 0 is infinite", - "run-time", SCSC_DEFAULT_MAX_RECORDS_PER_READ); - -static int scsc_double_buffer_sz = DEFAULT_TBUF_SZ; -module_param(scsc_double_buffer_sz, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(scsc_double_buffer_sz, - "Determines the size of the per-reader allocted double buffer.", - "run-time", DEFAULT_TBUF_SZ); - -/** - * BIG NOTE on DOUBLE BUFFERING. - * - * In order to extract data from the ring buffer, protected by spinlocks, - * to user space we use a double buffer: data is so finally copied to - * userspace from a temporary double buffer, after having copied into it - * ALL the desired content and after all the spinlocks have been released. - * In order to avoid use of an additional mutex to protect such temporary - * buffer from multiple readers access we use a oneshot throwaway buffer - * dedicated to each reader and allocated at opening time. - * The most straightforward way to do this thing would have been to simply - * allocate such buffer inside the read method and throw it away on exit: - * this is what underlying printk mechanism does via a simple kmalloc. - * BUT we decided INSTEAD to use this buffer ALSO as a sort of caching - * area for each reader in order to cope with under-sized user read-request; - * basically no matter what the user has asked in term of size of the read - * request we'll ALWAYS RETRIEVE multiple of whole records from the ring, - * one record being the minimum internal ring-read-request this way. - * So no matter if the user ask for a few bytes, less than the next record - * size, we'll retrieve ONE WHOLE record from the ring into the double buffer: - * this way on the next read request we'll have already a cached copy of the - * record and we could deal with it inside the read callback without the - * need to access the ring anymore for such record. - * The main reason for this is that if we had instead accessed the ring and - * retrieved ONLY a fraction of the record, on the next request we could NOT - * be able to provide the remaining part of the record because, being the ring - * an overwriting buffer, it could have wrap in the meantime and we could have - * simply lost that data: this condition would have lead us to return to - * user partial truncated records when we hit this overwrap condition. - * Following instead the approach of WHOLE records retrieval we can instead be - * sure to always retrieve fully correct records, despite being vulnerable - * anyway to loss of data (whole records) while reading if fast writers - * overwrite our data. (since we'll never ever want to slow down and starve a - * writer.) - */ -static struct dentry *scsc_debugfs_root; -static atomic_t scsc_debugfs_root_refcnt; -static char *global_fmt_string = "%s"; - -/** - * Generic open/close calls to use with every logring debugfs file. - * Any file in debugfs has an underlying associated ring buffer: - * opening ANY of these with O_TRUNC leads to ring_buffer truncated - * to zero len. - */ -static int debugfile_open(struct inode *ino, struct file *filp) -{ - struct scsc_ibox *i = NULL; - - if (!filp->private_data) { - i = kzalloc(sizeof(*i), GFP_KERNEL); - if (!i) - return -EFAULT; - i->rb = ino->i_private; - filp->private_data = i; - } else { - i = filp->private_data; - } - /* tbuf sz is now runtime-configurable so try a few fallback methods */ - i->tbuf = kmalloc(scsc_double_buffer_sz, GFP_KERNEL); - /* Making sure we fallback to a safe size DEFAULT_TBUF_SZ */ - if (!i->tbuf) { - i->tbuf = vmalloc(scsc_double_buffer_sz); - pr_err("LogRing: FAILED tbuf allocation of %d bytes...retried vmalloc()...\n", - scsc_double_buffer_sz); - if (!i->tbuf) { - scsc_double_buffer_sz = DEFAULT_TBUF_SZ; - pr_err("LogRing: FAILED tbuf vmalloc...using DEFAULT %d bytes size.\n", - scsc_double_buffer_sz); - i->tbuf = kmalloc(scsc_double_buffer_sz, GFP_KERNEL); - if (!i->tbuf) { - pr_err("LogRing: FAILED DEFINITELY allocation...aborting\n"); - kfree(i); - return -ENOMEM; - } - } else { - i->tbuf_vm = true; - } - } - i->tsz = scsc_double_buffer_sz; - pr_info("LogRing: Allocated per-reader tbuf of %d bytes\n", - scsc_double_buffer_sz); - /* Truncate when attempting to write RO files samlog and samsg */ - if (filp->f_flags & (O_WRONLY | O_RDWR) && - filp->f_flags & O_TRUNC) { - unsigned long flags; - - raw_spin_lock_irqsave(&i->rb->lock, flags); - scsc_ring_truncate(i->rb); - raw_spin_unlock_irqrestore(&i->rb->lock, flags); - pr_info("LogRing Truncated to zerolen\n"); - return -EACCES; - } - return 0; -} - -static int debugfile_release(struct inode *ino, struct file *filp) -{ - struct scsc_ibox *i = NULL; - - if (!filp->private_data) - return -EFAULT; - i = filp->private_data; - if (!i->tbuf_vm) - kfree(i->tbuf); - else - vfree(i->tbuf); - i->tbuf = NULL; - - /* Were we using a snapshot ? Free it.*/ - if (i->saved_live_rb) { - vfree(i->rb->buf); - kfree(i->rb); - } - /* Being paranoid... */ - filp->private_data = NULL; - kfree(i); - return 0; -} - -/** - * Initialize references for subsequent cached reads: in fact if - * data retrieved from the ring was more than the count-bytes required by - * the caller of this read, we can keep such data stored in tbuf and provide - * it to this same reader on its next read-call. - * - * @i: contains references useful to this reader - * @retrieved_bytes: how many bytes have been stored in tbuf - * @count: a pointer to the count bytes required by this reader - * for this call. We'll manipulate this to return an - * appropriate number of bytes. - */ -static inline -size_t init_cached_read(struct scsc_ibox *i, - size_t retrieved_bytes, size_t *count) -{ - if (retrieved_bytes <= *count) { - *count = retrieved_bytes; - } else { - i->t_off = *count; - i->t_used = retrieved_bytes - *count; - i->cached_reads += *count; - } - - return 0; -} - -/** - * Here we'll serve to user space the next available chunk of - * record directly from the tbuf double buffer without - * accessing the ring anymore. - * - * @i: contains references useful to this reader - * @count: a pointer to the count bytes required by this reader - * for this call. We'll manipulate this to return an - * appropriate number of bytes. - */ -static inline -size_t process_cached_read_data(struct scsc_ibox *i, size_t *count) -{ - size_t offset = 0; - - offset = i->t_off; - if (i->t_used <= *count) { - /* this was the last chunk cached */ - *count = i->t_used; - i->t_off = 0; - i->t_used = 0; - } else { - i->t_off += *count; - i->t_used -= *count; - i->cached_reads += *count; - } - - return offset; -} - -/** - * This file operation read from the ring using common routines, starting its - * read from head: in other words it immediately blocks waiting for some data to - * arrive. As soon as some data arrives and head moves away, the freshly - * available data is returned to userspace up to the required size , and this - * call goes back to sleeping waiting for more data. - * - * NOTE - * ---- - * The need to copy_to_user imposes the use of a temp buffer tbuf which is used - * as a double buffer: being allocated to this reader on open() we do NOT need - * any additional form of mutual exclusion. - * Moreover we use such buffer here as an area to cache the retrieved records: - * if the retrieved record size is bigger than the count bytes required by user - * we'll return less data at first and then deal with the following requests - * pumping data directly from the double buffer without accessing the ring. - */ -static ssize_t samsg_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - unsigned long flags; - loff_t current_head = 0; - struct scsc_ibox *i = NULL; - size_t off = 0; - size_t retrieved_bytes = 0; - - if (!filp->private_data || !access_ok(VERIFY_WRITE, ubuf, count)) - return -ENOMEM; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - /* open() assures us that this private data is certainly non-NULL */ - i = filp->private_data; - if (!i->t_used) { - raw_spin_lock_irqsave(&i->rb->lock, flags); - current_head = *f_pos ? i->f_pos : i->rb->head; - while (current_head == i->rb->head) { - raw_spin_unlock_irqrestore(&i->rb->lock, flags); - if (wait_event_interruptible(i->rb->wq, - current_head != i->rb->head)) - return -ERESTARTSYS; - raw_spin_lock_irqsave(&i->rb->lock, flags); - } - retrieved_bytes = read_next_records(i->rb, - scsc_max_records_per_read, - ¤t_head, i->tbuf, i->tsz); - /* We MUST keep track of the the last known READ record - * in order to keep going from the same place on the next - * read call coming from the same userspace process... - * ...this could NOT necessarily be the HEAD at the end of this - * read if we asked for few records. - * So we must annotate the really last read record got back, - * returned in current_head, inside i->f_pos in order to have a - * reference for the next read call by the same reader. - */ - i->f_pos = current_head; - raw_spin_unlock_irqrestore(&i->rb->lock, flags); - /* ANYWAY we could have got back more data from the ring (ONLY - * multiple of whole records) than required by usersapce. - */ - off = init_cached_read(i, retrieved_bytes, &count); - } else { - /* Serve this read-request directly from cached data without - * accessing the ring - */ - off = process_cached_read_data(i, &count); - } - if (copy_to_user(ubuf, i->tbuf + off, count)) - return -EFAULT; - *f_pos += count; - return count; -} - -/** - * This seek op assumes let userspace believe that it's dealing with a regular - * plain file, so f_pos is modified accordingly (linearly till the maximum - * number SCSC_LOGGED_BYTES is reached); in fact it's up to - * the read/write ops to properly 'cast' this value to a modulus value as - * required by the underlying ring buffer. This operates only on samlog. - */ -loff_t debugfile_llseek(struct file *filp, loff_t off, int whence) -{ - loff_t newpos, maxpos; - struct scsc_ibox *i = NULL; - unsigned long flags; - - if (!filp->private_data) - return -EFAULT; - i = filp->private_data; - raw_spin_lock_irqsave(&i->rb->lock, flags); - maxpos = SCSC_LOGGED_BYTES(i->rb) >= 1 ? - SCSC_LOGGED_BYTES(i->rb) - 1 : 0; - raw_spin_unlock_irqrestore(&i->rb->lock, flags); - switch (whence) { - case 0: /* SEEK_SET */ - newpos = (off <= maxpos) ? off : maxpos; - break; - case 1: /* SEEK_CUR */ - newpos = (filp->f_pos + off <= maxpos) ? - filp->f_pos + off : maxpos; - break; - case 2: /* SEEK_END */ - newpos = maxpos; - break; - default: /* can't happen */ - return -EINVAL; - } - if (newpos < 0) - return -EINVAL; - filp->f_pos = newpos; - return newpos; -} - -static int samsg_open(struct inode *ino, struct file *filp) -{ - int ret; - - ret = debugfile_open(ino, filp); -#ifdef CONFIG_SCSC_MXLOGGER - if (!ret) - scsc_service_register_observer(NULL, "LOGRING"); -#endif - return ret; -} - -static int samsg_release(struct inode *ino, struct file *filp) -{ -#ifdef CONFIG_SCSC_MXLOGGER - scsc_service_unregister_observer(NULL, "LOGRING"); -#endif - - return debugfile_release(ino, filp); -} - -const struct file_operations samsg_fops = { - .owner = THIS_MODULE, - .open = samsg_open, - .read = samsg_read, - .release = samsg_release, -}; - -/** - * This is the samlog open and it is used by samlog read-process to grab - * a per-reader dedicated static snapshot of the ring, in order to be able - * then to fetch records from a static immutable image of the ring buffer, - * without the need to stop the ring in the meantime. - * This way samlog dumps exactly a snapshot at-a-point-in-time of the ring - * limiting at the same time the contention with the writers: ring is - * 'spinlocked' ONLY durng the snapshot phase. - * Being the snapshot buffer big as the ring we use a vmalloc to limit - * possibility of failures (especially on non-AOSP builds). - * If such vmalloc allocation fails we then quietly keep on using the old - * method that reads directly from the live buffer. - */ -static int debugfile_open_snapshot(struct inode *ino, struct file *filp) -{ - int ret; - - ret = debugfile_open(ino, filp); - /* if regular debug_file_open has gone through, attempt snapshot */ - if (!ret) { - /* filp && filp->private_data NON-NULL by debugfile_open */ - void *snap_buf; - size_t snap_sz; - struct scsc_ibox *i = filp->private_data; - - /* This is read-only...no spinlocking needed */ - snap_sz = i->rb->bsz + i->rb->ssz; - /* Allocate here to minimize lock time... */ - snap_buf = vmalloc(snap_sz); - if (snap_buf) { - struct scsc_ring_buffer *snap_rb; - char snap_name[RNAME_SZ] = "snapshot"; - unsigned long flags; - - snprintf(snap_name, RNAME_SZ, "%s_snap", i->rb->name); - /* lock while snapshot is taken */ - raw_spin_lock_irqsave(&i->rb->lock, flags); - snap_rb = scsc_ring_get_snapshot(i->rb, snap_buf, snap_sz, snap_name); - raw_spin_unlock_irqrestore(&i->rb->lock, flags); - if (snap_rb) { - /* save real ring and swap into the snap_shot */ - i->saved_live_rb = i->rb; - i->rb = snap_rb; - } else { - vfree(snap_buf); - snap_buf = NULL; - } - } - - /* Warns when not possible to use a snapshot */ - if (!snap_buf) - pr_warn("LogRing: no snapshot available, samlog dump from live ring.\n"); - } - - return ret; -} - -/** - * samlog_read - Reads from the ring buffer the required number of bytes - * starting from the start of the ring. It is usually used to dump the - * whole ring buffer taking a snapshot at-a-point-in-time. - * - * If it had been possible at opening time to take a static snapshot of - * the ring, this routine will fetch records from such a snapshot without - * the need to lock the ring; if instead no snapshot was taken it reverts - * to the usual locked-access pattern. - * - * This function as a usual .read fops returns the number of bytes - * effectively read, and this could: - * - equal the required count bytes - * - be less than the required bytes if: less data WAS available - * (since we only GOT whole records at time from the ring) - * Returning less bytes usually triggers the userapp to reissue the syscall - * to complete the read up to the originaly required number of bytes. - * - be ZERO if NO more data available..this causes the reading userspace - * process to stop reading usually. - */ -static ssize_t samlog_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - struct scsc_ibox *i = NULL; - size_t off = 0, retrieved_bytes = 0; - - if (!filp->private_data) - return -EFAULT; - i = filp->private_data; - if (!i->t_used) { - unsigned long flags; - - /* Lock ONLY if NOT using a snapshot */ - if (!i->saved_live_rb) - raw_spin_lock_irqsave(&i->rb->lock, flags); - /* On first read from userspace f_pos will be ZERO and in this - * case we'll want to trigger a read from the very beginning of - * ring (tail) and set i->f_pos accordingly. - * Internal RING API returns in i->f_pos the next record to - * read: when reading process has wrapped over you'll get back - * an f_pos ZERO as next read. - */ - if (*f_pos == 0) - i->f_pos = i->rb->tail; - retrieved_bytes = read_next_records(i->rb, - scsc_max_records_per_read, - &i->f_pos, i->tbuf, i->tsz); - if (!i->saved_live_rb) - raw_spin_unlock_irqrestore(&i->rb->lock, flags); - /* ANYWAY we could have got back more data from the ring (ONLY - * multiple of whole records) than required by userspace. - */ - off = init_cached_read(i, retrieved_bytes, &count); - } else { - /* Serve this read-request directly from cached data without - * accessing the ring - */ - off = process_cached_read_data(i, &count); - } - if (copy_to_user(ubuf, i->tbuf + off, count)) - return -EFAULT; - *f_pos += count; - return count; -} - -const struct file_operations samlog_fops = { - .owner = THIS_MODULE, - .open = debugfile_open_snapshot, - .read = samlog_read, - .llseek = debugfile_llseek, - .release = debugfile_release, -}; - -static int statfile_open(struct inode *ino, struct file *filp) -{ - if (!filp->private_data) - filp->private_data = ino->i_private; - if (!filp->private_data) - return -EFAULT; - return 0; -} - -static int statfile_release(struct inode *ino, struct file *filp) -{ - if (!filp->private_data) - filp->private_data = ino->i_private; - if (!filp->private_data) - return -EFAULT; - return 0; -} - - -/* A simple read to dump some stats about the ring buffer. */ -static ssize_t statfile_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - unsigned long flags; - size_t bsz = 0; - loff_t head = 0, tail = 0, used = 0, max_chunk = 0, logged = 0, - last = 0; - int slen = 0, records = 0, wraps = 0, oos = 0; - u64 written = 0; - char statstr[STATSTR_SZ] = {}; - struct scsc_ring_buffer *rb = filp->private_data; - - raw_spin_lock_irqsave(&rb->lock, flags); - bsz = rb->bsz; - head = rb->head; - tail = rb->tail; - last = rb->last; - written = rb->written; - records = rb->records; - wraps = rb->wraps; - oos = rb->oos; - used = SCSC_USED_BYTES(rb); - max_chunk = SCSC_RING_FREE_BYTES(rb); - logged = SCSC_LOGGED_BYTES(rb); - raw_spin_unlock_irqrestore(&rb->lock, flags); - - slen = snprintf(statstr, STATSTR_SZ, - "sz:%zd used:%lld free:%lld logged:%lld records:%d\nhead:%lld tail:%lld last:%lld written:%lld wraps:%d oos:%d\n", - bsz, used, max_chunk, logged, records, - head, tail, last, written, wraps, oos); - if (slen >= 0 && *f_pos < slen) { - count = (count <= slen - *f_pos) ? count : (slen - *f_pos); - if (copy_to_user(ubuf, statstr + *f_pos, count)) - return -EFAULT; - *f_pos += count; - } else - count = 0; - return count; -} - -const struct file_operations stat_fops = { - .owner = THIS_MODULE, - .open = statfile_open, - .read = statfile_read, - .release = statfile_release, -}; - -/** - * This implement samwrite interface to INJECT log lines into the ring from - * user space. The support, thought as an aid for testing mainly, is - * minimal, so the interface allows only for simple %s format string injection. - */ -static int samwritefile_open(struct inode *ino, struct file *filp) -{ - if (!filp->private_data) { - struct write_config *wc = - kzalloc(sizeof(struct write_config), GFP_KERNEL); - if (wc) { - wc->fmt = global_fmt_string; - wc->buf_sz = SAMWRITE_BUFSZ; - } - filp->private_data = wc; - } - if (!filp->private_data) - return -EFAULT; - return 0; -} - - -static int samwritefile_release(struct inode *ino, struct file *filp) -{ - kfree(filp->private_data); - filp->private_data = NULL; - return 0; -} - -/** - * User injected string content is pushed to the ring as simple %s fmt string - * content using the TEST_ME tag. Default debuglevel (6 - INFO)will be used. - */ -static ssize_t samwritefile_write(struct file *filp, const char __user *ubuf, - size_t count, loff_t *f_pos) -{ - ssize_t written_bytes = 0; - struct write_config *wc = filp->private_data; - - if (wc) { - /* wc->buf is null terminated as it's kzalloc'ed */ - count = count < wc->buf_sz ? count : wc->buf_sz - 1; - if (copy_from_user(wc->buf, ubuf, count)) - return -EINVAL; - written_bytes = scsc_printk_tag(NO_ECHO_PRK, TEST_ME, - wc->fmt, wc->buf); - /* Handle the case where the message is filtered out by - * droplevel filters...zero is returned BUT we do NOT want - * the applications to keep trying...it's NOT a transient - * error...at least till someone changes droplevels. - */ - if (!written_bytes) { - pr_info("samwrite wrote 0 bytes...droplevels filtering ?\n"); - return -EPERM; - } - /* Returned written bytes should be normalized since - * lower level functions returns the number of bytes - * effectively written including the prepended header - * file... IF, when required to write n, we return n+X, - * some applications could behave badly trying to access - * file at *fpos=n+X next time, ending up in a regular - * EFAULT error anyway. - */ - if (written_bytes > count) - written_bytes = count; - *f_pos += written_bytes; - } - - return written_bytes; -} - -const struct file_operations samwrite_fops = { - .owner = THIS_MODULE, - .open = samwritefile_open, - .write = samwritefile_write, - .release = samwritefile_release, -}; - -/** - * Initializes debugfs support build the proper debugfs file dentries: - * - entries in debugfs are created under /sys/kernel/debugfs/scsc/@name/ - * - using the provided rb ring buffer as underlying ring buffer, storing it - * into inode ptr for future retrieval (via open) - * - registers the proper fops - */ -void __init *samlog_debugfs_init(const char *root_name, void *rb) -{ - struct scsc_debugfs_info *di = NULL; - - if (!rb || !root_name) - return NULL; - di = kmalloc(sizeof(*di), GFP_KERNEL); - if (!di) - return NULL; - if (!scsc_debugfs_root) { - /* I could have multiple rings debugfs entry all rooted at - * the same /sys/kernel/debug/scsc/...so such entry could - * already exist. - */ - scsc_debugfs_root = debugfs_create_dir(SCSC_DEBUGFS_ROOT, NULL); - if (!scsc_debugfs_root) - goto no_root; - } - di->rootdir = scsc_debugfs_root; - di->bufdir = debugfs_create_dir(root_name, di->rootdir); - if (!di->bufdir) - goto no_buf; - atomic_inc(&scsc_debugfs_root_refcnt); - /* Saving ring ref @rb to Inode */ - di->samsgfile = debugfs_create_file(SCSC_SAMSG_FNAME, 0444, - di->bufdir, rb, &samsg_fops); - if (!di->samsgfile) - goto no_samsg; - /* Saving ring ref @rb to Inode */ - di->samlogfile = debugfs_create_file(SCSC_SAMLOG_FNAME, 0444, - di->bufdir, rb, &samlog_fops); - if (!di->samlogfile) - goto no_samlog; - di->statfile = debugfs_create_file(SCSC_STAT_FNAME, 0444, - di->bufdir, rb, &stat_fops); - if (!di->statfile) - goto no_statfile; - - di->samwritefile = debugfs_create_file(SCSC_SAMWRITE_FNAME, 0220, - di->bufdir, NULL, - &samwrite_fops); - if (!di->samwritefile) - goto no_samwrite; - - pr_info("Samlog Debugfs Initialized\n"); - return di; - -no_samwrite: - debugfs_remove(di->statfile); -no_statfile: - debugfs_remove(di->samlogfile); -no_samlog: - debugfs_remove(di->samsgfile); -no_samsg: - debugfs_remove(di->bufdir); - atomic_dec(&scsc_debugfs_root_refcnt); -no_buf: - if (!atomic_read(&scsc_debugfs_root_refcnt)) { - debugfs_remove(scsc_debugfs_root); - scsc_debugfs_root = NULL; - } -no_root: - kfree(di); - return NULL; -} - -void __exit samlog_debugfs_exit(void **priv) -{ - struct scsc_debugfs_info **di = NULL; - - if (!priv) - return; - di = (struct scsc_debugfs_info **)priv; - if (di && *di) { - debugfs_remove_recursive(scsc_debugfs_root); - atomic_dec(&scsc_debugfs_root_refcnt); - if (!atomic_read(&scsc_debugfs_root_refcnt)) { - debugfs_remove(scsc_debugfs_root); - scsc_debugfs_root = NULL; - } - kfree(*di); - *di = NULL; - } - pr_info("Debugfs Cleaned Up\n"); -} diff --git a/drivers/misc/samsung/scsc/scsc_logring_debugfs.h b/drivers/misc/samsung/scsc/scsc_logring_debugfs.h deleted file mode 100644 index 9aab70f7c5cc..000000000000 --- a/drivers/misc/samsung/scsc/scsc_logring_debugfs.h +++ /dev/null @@ -1,61 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ - -#ifndef _SCSC_LOGRING_DEBUGFS_H_ -#define _SCSC_LOGRING_DEBUGFS_H_ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "scsc_logring_ring.h" - -#define STATSTR_SZ 256 -#define SCSC_DEBUGFS_ROOT "scsc" -#define SCSC_SAMSG_FNAME "samsg" -#define SCSC_SAMLOG_FNAME "samlog" -#define SCSC_STAT_FNAME "stat" -#define SCSC_SAMWRITE_FNAME "samwrite" - -#define SAMWRITE_BUFSZ 2048 -#define SCSC_DEFAULT_MAX_RECORDS_PER_READ 1 - -struct scsc_ibox { - struct scsc_ring_buffer *rb; - char *tbuf; - size_t tsz; - bool tbuf_vm; - size_t t_off; - size_t t_used; - size_t cached_reads; - loff_t f_pos; - struct scsc_ring_buffer *saved_live_rb; -}; - -struct scsc_debugfs_info { - struct dentry *rootdir; - struct dentry *bufdir; - struct dentry *samsgfile; - struct dentry *samlogfile; - struct dentry *statfile; - struct dentry *samwritefile; -}; - -struct write_config { - char *fmt; - size_t buf_sz; - char buf[SAMWRITE_BUFSZ]; -}; - -void *samlog_debugfs_init(const char *name, void *rb) __init; -void samlog_debugfs_exit(void **priv) __exit; - -#endif /* _SCSC_LOGRING_DEBUGFS_H_ */ diff --git a/drivers/misc/samsung/scsc/scsc_logring_main.c b/drivers/misc/samsung/scsc/scsc_logring_main.c deleted file mode 100644 index d985068e7dbe..000000000000 --- a/drivers/misc/samsung/scsc/scsc_logring_main.c +++ /dev/null @@ -1,663 +0,0 @@ -/******************************************************************************** - * - * Copyright (c) 2016 - 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ********************************************************************************/ -#include "scsc_logring_main.h" -#include "scsc_logring_ring.h" -#include "scsc_logring_debugfs.h" -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif - -/* Global module parameters */ -static int cached_enable; -static int enable = DEFAULT_ENABLE_LOGRING; -static bool initialized; -#ifndef CONFIG_SCSC_STATIC_RING_SIZE -static int ringsize = DEFAULT_RING_BUFFER_SZ; -#else -static int ringsize = CONFIG_SCSC_STATIC_RING_SIZE; -#endif -static int prepend_header = DEFAULT_ENABLE_HEADER; -static int default_dbglevel = DEFAULT_DBGLEVEL; -static int scsc_droplevel_wlbt = DEFAULT_DROPLEVEL; -static int scsc_droplevel_all = DEFAULT_ALL_DISABLED; -static int scsc_droplevel_atomic = DEFAULT_DROPLEVEL; -static int scsc_redirect_to_printk_droplvl = DEFAULT_REDIRECT_DROPLVL; -static int scsc_reset_all_droplevels_to; - -struct scsc_ring_buffer *the_ringbuf; - -#ifdef CONFIG_SCSC_LOG_COLLECTION -static int logring_collect(struct scsc_log_collector_client *collect_client, size_t size); - -struct scsc_log_collector_client logring_collect_client = { - .name = "Logring", - .type = SCSC_LOG_CHUNK_LOGRING, - .collect_init = NULL, - .collect = logring_collect, - .collect_end = NULL, - .prv = NULL, -}; -#endif - -/* Module init and ring buffer allocation */ -int __init samlog_init(void) -{ - struct scsc_ring_buffer *rb = NULL; - - pr_debug("Samlog Init\n"); - if (!enable) { - pr_info("Samlog: module disabled...NOT starting.\n"); - return 0; - } - if (the_ringbuf != NULL) { - pr_info("Samlog: Ring:%s already initialized...skipping.\n", - the_ringbuf->name); - return 0; - } - /* Check for power of two compliance with std Kernel func */ - if (!is_power_of_2(ringsize)) { - ringsize = DEFAULT_RING_BUFFER_SZ; - pr_info("Samlog: scsc_logring.ringsize MUST be power-of-two. Using default: %d\n", - ringsize); - } - rb = alloc_ring_buffer(ringsize, BASE_SPARE_SZ, DEBUGFS_RING0_ROOT); - - if (!rb) - goto tfail; - rb->private = samlog_debugfs_init(rb->name, rb); - if (!rb->private) - pr_info("Samlog: Cannot Initialize DebugFS.\n"); -#ifndef CONFIG_SCSC_STATIC_RING_SIZE - pr_info("scsc_logring:: Allocated ring buffer of size %zd bytes.\n", - rb->bsz); -#else - pr_info("scsc_logring:: Allocated STATIC ring buffer of size %zd bytes.\n", - rb->bsz); -#endif - the_ringbuf = rb; - initialized = true; - pr_info("Samlog Loaded.\n"); - scsc_printk_tag(FORCE_PRK, NO_TAG, "Samlog Started.\n"); - scsc_printk_tag(NO_ECHO_PRK, NO_TAG, - "Allocated ring buffer of size %zd bytes at %p - %p\n", - rb->bsz, virt_to_phys((const volatile void *)rb->buf), - virt_to_phys((const volatile void *)(rb->buf + rb->bsz))); - scsc_printk_tag(NO_ECHO_PRK, NO_TAG, - "Using THROWAWAY DYNAMIC per-reader buffer.\n"); - -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_register_client(&logring_collect_client); -#endif - return 0; - -tfail: - pr_err("Samlog Initialization Failed. LogRing disabled.\n"); - return -ENODEV; -} - -void __exit samlog_exit(void) -{ - if (!the_ringbuf) { - pr_err("Cannot UNLOAD ringbuf\n"); - return; - } - if (the_ringbuf && the_ringbuf->private) - samlog_debugfs_exit(&the_ringbuf->private); - initialized = false; - free_ring_buffer(the_ringbuf); - the_ringbuf = NULL; -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_unregister_client(&logring_collect_client); -#endif - pr_info("Samlog Unloaded\n"); -} - -module_init(samlog_init); -module_exit(samlog_exit); - -module_param(enable, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(enable, "Enable/Disable scsc_logring as a whole.", - "load-time", DEFAULT_ENABLE_LOGRING); - -#ifndef CONFIG_SCSC_STATIC_RING_SIZE -module_param(ringsize, int, S_IRUGO); -SCSC_MODPARAM_DESC(ringsize, - "Ring buffer size. Available ONLY if ring is NOT statically allocated.", - "run-time", DEFAULT_RING_BUFFER_SZ); -#endif - -module_param(prepend_header, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(prepend_header, "Enable/disable header prepending. ", - "run-time", DEFAULT_ENABLE_HEADER); - -module_param(default_dbglevel, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(default_dbglevel, - "The default debug level assigned to messages when NOT explicitly specified.", - "run-time", DEFAULT_DBGLEVEL); - -module_param(scsc_droplevel_wlbt, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(scsc_droplevel_wlbt, - "Droplevels for the 'no_tag/wlbt' tag family.", "run-time", - DEFAULT_DROP_ALL); - -module_param(scsc_droplevel_all, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(scsc_droplevel_all, - "This droplevel overrides any other, if set to a value >= 0", - "run-time", DEFAULT_ALL_DISABLED); - -module_param(scsc_redirect_to_printk_droplvl, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(scsc_redirect_to_printk_droplvl, - "Echoing messages up to the specified loglevel also to kernel standard ring buffer.", - "run-time", DEFAULT_REDIRECT_DROPLVL); - -module_param(scsc_droplevel_atomic, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(scsc_droplevel_atomic, - "This droplevel is applied to logmsg emitted in atomic context.", - "run-time", DEFAULT_KEEP_ALL); - -/** - * This macro code has been freely 'inspired' (read copied) from the - * slsi_ original/old debug.c implementaion: it takes care to register - * a new TAG with the debug subsystem including a module param to - * dynamically configure the droplevel for the specified tag at runtime. - * - * ALL debug is ON by default at FULL DEBUG LEVEL. - * There are THREE intended exceptions to this that instead stick to - * level 7: PLAT_MIF MBULK and MXLOG_TRANS tags. - * - * NOTE_CREATING_TAGS: when adding a tag here REMEMBER to add it also - * where required, taking care to maintain the same ordering. - * (Search 4 NOTE_CREATING_TAGS) - */ - -/** - * This macros define module parameters used to configure per-subsystem - * filtering, and assign a default DROPLEVEL. - * - * NOTE THAT the default DROPLEVEL indicates the default value FROM which - * the system will start to discard messages, so as an example: - * - * - if set to SCSC_DBG1 (7) every message with a dbglvl >= 7 will be discarded - * - if set to SCSC_FULL_DEBUG (11) every message is logged - * - * Name, Default DROPLEVEL , FilterTag - */ -ADD_DEBUG_MODULE_PARAM(binary, SCSC_FULL_DEBUG, BINARY); -ADD_DEBUG_MODULE_PARAM(bin_wifi_ctrl_rx, SCSC_FULL_DEBUG, BIN_WIFI_CTRL_RX); -ADD_DEBUG_MODULE_PARAM(bin_wifi_data_rx, SCSC_FULL_DEBUG, BIN_WIFI_DATA_RX); -ADD_DEBUG_MODULE_PARAM(bin_wifi_ctrl_tx, SCSC_FULL_DEBUG, BIN_WIFI_CTRL_TX); -ADD_DEBUG_MODULE_PARAM(bin_wifi_data_tx, SCSC_FULL_DEBUG, BIN_WIFI_DATA_TX); -ADD_DEBUG_MODULE_PARAM(wifi_rx, SCSC_FULL_DEBUG, WIFI_RX); -ADD_DEBUG_MODULE_PARAM(wifi_tx, SCSC_FULL_DEBUG, WIFI_TX); -ADD_DEBUG_MODULE_PARAM(bt_common, SCSC_FULL_DEBUG, BT_COMMON); -ADD_DEBUG_MODULE_PARAM(bt_h4, SCSC_FULL_DEBUG, BT_H4); -ADD_DEBUG_MODULE_PARAM(bt_fw, SCSC_FULL_DEBUG, BT_FW); -ADD_DEBUG_MODULE_PARAM(bt_rx, SCSC_FULL_DEBUG, BT_RX); -ADD_DEBUG_MODULE_PARAM(bt_tx, SCSC_FULL_DEBUG, BT_TX); -ADD_DEBUG_MODULE_PARAM(cpktbuff, SCSC_DBG4, CPKTBUFF); -ADD_DEBUG_MODULE_PARAM(fw_load, SCSC_FULL_DEBUG, FW_LOAD); -ADD_DEBUG_MODULE_PARAM(fw_panic, SCSC_FULL_DEBUG, FW_PANIC); -ADD_DEBUG_MODULE_PARAM(gdb_trans, SCSC_DBG1, GDB_TRANS); -ADD_DEBUG_MODULE_PARAM(mif, SCSC_FULL_DEBUG, MIF); -ADD_DEBUG_MODULE_PARAM(clk20, SCSC_FULL_DEBUG, CLK20); -ADD_DEBUG_MODULE_PARAM(clk20_test, SCSC_FULL_DEBUG, CLK20_TEST); -ADD_DEBUG_MODULE_PARAM(fm, SCSC_FULL_DEBUG, FM); -ADD_DEBUG_MODULE_PARAM(fm_test, SCSC_FULL_DEBUG, FM_TEST); -ADD_DEBUG_MODULE_PARAM(mx_file, SCSC_FULL_DEBUG, MX_FILE); -ADD_DEBUG_MODULE_PARAM(mx_fw, SCSC_FULL_DEBUG, MX_FW); -ADD_DEBUG_MODULE_PARAM(mx_sampler, SCSC_FULL_DEBUG, MX_SAMPLER); -ADD_DEBUG_MODULE_PARAM(mxlog_trans, SCSC_DBG1, MXLOG_TRANS); -ADD_DEBUG_MODULE_PARAM(mxman, SCSC_FULL_DEBUG, MXMAN); -ADD_DEBUG_MODULE_PARAM(mxman_test, SCSC_FULL_DEBUG, MXMAN_TEST); -ADD_DEBUG_MODULE_PARAM(mxmgt_trans, SCSC_FULL_DEBUG, MXMGT_TRANS); -ADD_DEBUG_MODULE_PARAM(mx_mmap, SCSC_DBG1, MX_MMAP); -ADD_DEBUG_MODULE_PARAM(mx_proc, SCSC_FULL_DEBUG, MX_PROC); -ADD_DEBUG_MODULE_PARAM(panic_mon, SCSC_FULL_DEBUG, PANIC_MON); -ADD_DEBUG_MODULE_PARAM(pcie_mif, SCSC_FULL_DEBUG, PCIE_MIF); -ADD_DEBUG_MODULE_PARAM(plat_mif, SCSC_DBG1, PLAT_MIF); -ADD_DEBUG_MODULE_PARAM(kic_common, SCSC_FULL_DEBUG, KIC_COMMON); -ADD_DEBUG_MODULE_PARAM(wlbtd, SCSC_FULL_DEBUG, WLBTD); -ADD_DEBUG_MODULE_PARAM(wlog, SCSC_DEBUG, WLOG); -ADD_DEBUG_MODULE_PARAM(lerna, SCSC_FULL_DEBUG, LERNA); -ADD_DEBUG_MODULE_PARAM(mxcfg, SCSC_FULL_DEBUG, MX_CFG); -#ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY -ADD_DEBUG_MODULE_PARAM(init_deinit, SCSC_FULL_DEBUG, SLSI_INIT_DEINIT); -ADD_DEBUG_MODULE_PARAM(netdev, SCSC_DBG4, SLSI_NETDEV); -ADD_DEBUG_MODULE_PARAM(cfg80211, SCSC_FULL_DEBUG, SLSI_CFG80211); -ADD_DEBUG_MODULE_PARAM(mlme, SCSC_FULL_DEBUG, SLSI_MLME); -ADD_DEBUG_MODULE_PARAM(summary_frames, SCSC_FULL_DEBUG, SLSI_SUMMARY_FRAMES); -ADD_DEBUG_MODULE_PARAM(hydra, SCSC_FULL_DEBUG, SLSI_HYDRA); -ADD_DEBUG_MODULE_PARAM(tx, SCSC_FULL_DEBUG, SLSI_TX); -ADD_DEBUG_MODULE_PARAM(rx, SCSC_FULL_DEBUG, SLSI_RX); -ADD_DEBUG_MODULE_PARAM(udi, SCSC_DBG4, SLSI_UDI); -ADD_DEBUG_MODULE_PARAM(wifi_fcq, SCSC_DBG4, SLSI_WIFI_FCQ); -ADD_DEBUG_MODULE_PARAM(hip, SCSC_FULL_DEBUG, SLSI_HIP); -ADD_DEBUG_MODULE_PARAM(hip_init_deinit, SCSC_FULL_DEBUG, SLSI_HIP_INIT_DEINIT); -ADD_DEBUG_MODULE_PARAM(hip_fw_dl, SCSC_FULL_DEBUG, SLSI_HIP_FW_DL); -ADD_DEBUG_MODULE_PARAM(hip_sdio_op, SCSC_FULL_DEBUG, SLSI_HIP_SDIO_OP); -ADD_DEBUG_MODULE_PARAM(hip_ps, SCSC_FULL_DEBUG, SLSI_HIP_PS); -ADD_DEBUG_MODULE_PARAM(hip_th, SCSC_FULL_DEBUG, SLSI_HIP_TH); -ADD_DEBUG_MODULE_PARAM(hip_fh, SCSC_FULL_DEBUG, SLSI_HIP_FH); -ADD_DEBUG_MODULE_PARAM(hip_sig, SCSC_FULL_DEBUG, SLSI_HIP_SIG); -ADD_DEBUG_MODULE_PARAM(func_trace, SCSC_FULL_DEBUG, SLSI_FUNC_TRACE); -ADD_DEBUG_MODULE_PARAM(test, SCSC_FULL_DEBUG, SLSI_TEST); -ADD_DEBUG_MODULE_PARAM(src_sink, SCSC_FULL_DEBUG, SLSI_SRC_SINK); -ADD_DEBUG_MODULE_PARAM(fw_test, SCSC_DBG4, SLSI_FW_TEST); -ADD_DEBUG_MODULE_PARAM(rx_ba, SCSC_FULL_DEBUG, SLSI_RX_BA); -ADD_DEBUG_MODULE_PARAM(tdls, SCSC_FULL_DEBUG, SLSI_TDLS); -ADD_DEBUG_MODULE_PARAM(gscan, SCSC_FULL_DEBUG, SLSI_GSCAN); -ADD_DEBUG_MODULE_PARAM(mbulk, SCSC_DBG1, SLSI_MBULK); -ADD_DEBUG_MODULE_PARAM(smapper, SCSC_DBG1, SLSI_SMAPPER); -ADD_DEBUG_MODULE_PARAM(flowc, SCSC_FULL_DEBUG, SLSI_FLOWC); -#endif -ADD_DEBUG_MODULE_PARAM(test_me, SCSC_FULL_DEBUG, TEST_ME); - -/* Extend this list when you add ADD_DEBUG_MODULE_PARAM, above. - * You must also extend "enum scsc_logring_tags" - */ -int *scsc_droplevels[MAX_TAG + 1] = { - &scsc_droplevel_binary, - &scsc_droplevel_bin_wifi_ctrl_rx, - &scsc_droplevel_bin_wifi_data_rx, - &scsc_droplevel_bin_wifi_ctrl_tx, - &scsc_droplevel_bin_wifi_data_tx, - &scsc_droplevel_wlbt, - &scsc_droplevel_wifi_rx, - &scsc_droplevel_wifi_tx, - &scsc_droplevel_bt_common, - &scsc_droplevel_bt_h4, - &scsc_droplevel_bt_fw, - &scsc_droplevel_bt_rx, - &scsc_droplevel_bt_tx, - &scsc_droplevel_cpktbuff, - &scsc_droplevel_fw_load, - &scsc_droplevel_fw_panic, - &scsc_droplevel_gdb_trans, - &scsc_droplevel_mif, - &scsc_droplevel_clk20, - &scsc_droplevel_clk20_test, - &scsc_droplevel_fm, - &scsc_droplevel_fm_test, - &scsc_droplevel_mx_file, - &scsc_droplevel_mx_fw, - &scsc_droplevel_mx_sampler, - &scsc_droplevel_mxlog_trans, - &scsc_droplevel_mxman, - &scsc_droplevel_mxman_test, - &scsc_droplevel_mxmgt_trans, - &scsc_droplevel_mx_mmap, - &scsc_droplevel_mx_proc, - &scsc_droplevel_panic_mon, - &scsc_droplevel_pcie_mif, - &scsc_droplevel_plat_mif, - &scsc_droplevel_kic_common, - &scsc_droplevel_wlbtd, - &scsc_droplevel_wlog, - &scsc_droplevel_lerna, - &scsc_droplevel_mxcfg, -#ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY - &scsc_droplevel_init_deinit, - &scsc_droplevel_netdev, - &scsc_droplevel_cfg80211, - &scsc_droplevel_mlme, - &scsc_droplevel_summary_frames, - &scsc_droplevel_hydra, - &scsc_droplevel_tx, - &scsc_droplevel_rx, - &scsc_droplevel_udi, - &scsc_droplevel_wifi_fcq, - &scsc_droplevel_hip, - &scsc_droplevel_hip_init_deinit, - &scsc_droplevel_hip_fw_dl, - &scsc_droplevel_hip_sdio_op, - &scsc_droplevel_hip_ps, - &scsc_droplevel_hip_th, - &scsc_droplevel_hip_fh, - &scsc_droplevel_hip_sig, - &scsc_droplevel_func_trace, - &scsc_droplevel_test, - &scsc_droplevel_src_sink, - &scsc_droplevel_fw_test, - &scsc_droplevel_rx_ba, - &scsc_droplevel_tdls, - &scsc_droplevel_gscan, - &scsc_droplevel_mbulk, - &scsc_droplevel_flowc, - &scsc_droplevel_smapper, -#endif - &scsc_droplevel_test_me, /* Must be last */ -}; - -#ifdef CONFIG_SCSC_LOG_COLLECTION -static int logring_collect(struct scsc_log_collector_client *collect_client, size_t size) -{ - int ret = 0, saved_droplevel; - - if (!the_ringbuf) - return 0; - - /** - * Inhibit logring during collection overriding with scsc_droplevel_all - */ - saved_droplevel = scsc_droplevel_all; - scsc_droplevel_all = DEFAULT_DROP_ALL; - - /* Write buffer */ - ret = scsc_log_collector_write(the_ringbuf->buf, the_ringbuf->bsz, 1); - - scsc_droplevel_all = saved_droplevel; - - return ret; -} -#endif - -static int scsc_reset_all_droplevels_to_set_param_cb(const char *val, - const struct kernel_param *kp) -{ - int ret = 0, i = 0; - long rval = 0; - - if (!val) - return -EINVAL; - ret = kstrtol(val, 10, &rval); - if (!ret) { - if (rval < 0) - return -EINVAL; - scsc_droplevel_wlbt = (int)rval; - for (i = 0; i < ARRAY_SIZE(scsc_droplevels); i++) - *scsc_droplevels[i] = (int)rval; - scsc_reset_all_droplevels_to = (int)rval; - scsc_printk_tag(FORCE_PRK, NO_TAG, - KERN_INFO"Reset ALL droplevels to %d\n", - scsc_reset_all_droplevels_to); - } - return ret; -} - -static struct kernel_param_ops scsc_reset_droplvl_ops = { - .set = scsc_reset_all_droplevels_to_set_param_cb, - .get = NULL, -}; -module_param_cb(scsc_reset_all_droplevels_to, &scsc_reset_droplvl_ops, - NULL, 0200); -MODULE_PARM_DESC(scsc_reset_all_droplevels_to, - "Reset ALL droplevels to the requested value. Effective @run-time."); - - -/* SCSC_PRINTK API and Helpers */ -static inline int get_debug_level(const char *fmt) -{ - int level; - - if (fmt && *fmt == SCSC_SOH && *(fmt + 1)) - level = *(fmt + 1) - '0'; - else - level = default_dbglevel; - return level; -} - -static inline void drop_message_level_macro(const char *fmt, char **msg) -{ - if (fmt && *fmt == SCSC_SOH && *(fmt + 1)) { - if (msg) - *msg = (char *)(fmt + 2); - } else if (msg) { - *msg = (char *)fmt; - } -} - -/** - * The workhorse function that receiving a droplevel to enforce, and a pair - * format_string/va_list decides what to do: - * - drop - * OR - * - insert into ring buffer accounting for wrapping - * - * ... then wakes up any waiting reading process - */ -static inline int _scsc_printk(int level, int tag, - const char *fmt, va_list args) -{ - int written = 0; - char *msg_head = NULL; - - if (!initialized || !enable || !fmt || - ((scsc_droplevel_all < 0 && level >= *scsc_droplevels[tag]) || - (scsc_droplevel_all >= 0 && level >= scsc_droplevel_all))) - return written; - drop_message_level_macro(fmt, &msg_head); - written = push_record_string(the_ringbuf, tag, level, - prepend_header, msg_head, args); - return written; -} - -/** - * Embeds the filtering behaviour towards std kenrel ring buffer for - * non binary stuff, and decides what to do based on current user config. - * Note that printk redirect doplevel filter is now completely disjoint - * from normal LogRing droplevel filters. - */ -static inline -void handle_klogbuf_out_string(int level, struct device *dev, int tag, - const char *fmt, va_list args, int force) -{ - if (IS_PRINTK_REDIRECT_ALLOWED(force, level, tag)) { - if (!dev) - vprintk_emit(0, level, NULL, 0, fmt, args); - else - dev_vprintk_emit(level, dev, fmt, args); - } -} - -const char *map2kern[] = { - KERN_EMERG, - KERN_ALERT, - KERN_CRIT, - KERN_ERR, - KERN_WARNING, - KERN_NOTICE, - KERN_INFO, - KERN_DEBUG -}; - -/** - * Embeds the filtering behaviour towards std kenrel ring buffer for - * BINARY stuff, and decides what to do based on current user config. - * Note that printk redirect doplevel filter is now completely disjoint - * from normal LogRing droplevel filters. - */ -static inline -void handle_klogbuf_out_binary(int level, int tag, const void *start, - size_t len, int force) -{ - if (IS_PRINTK_REDIRECT_ALLOWED(force, level, tag)) { - if (level < SCSC_MIN_DBG || level >= ARRAY_SIZE(map2kern)) - level = ARRAY_SIZE(map2kern) - 1; - print_hex_dump(map2kern[level], SCSC_PREFIX"SCSC_HEX->|", - DUMP_PREFIX_NONE, 16, 1, start, len, false); - } -} - -/* - * scsc_printk - it's main API entry to the event logging mechanism. Prints - * the specified format string to the underlying ring_buffer, injecting - * timestamp and context information at the start of the line while - * classifying and filtering the message suing the specified TAG identifier. - * - * This function assumes that you'll never write a line longer than - * BASE_SPARE_SZ bytes; if this limit is obeyed any input string is correctly - * wrapped when placed at the end of the buffer. Any longer line will be - * trucated. - * This function recognize Kernel style debug level KERN_, checking the FIRST - * byte for ASCII SOH in order to recognize if some printk style kernel debug - * level has been specified. - * SO you can use KERN_INFO KERN_ERR etc etc INLINE macros to specify the - * desired debug level: that will be checked against the droplevel specified. - * If NOT specified a default debug level is assigned following what specified - * in module parameter default_dbglevel. - * - * It's usually NOT used directly but through the means of utility macros that - * can be easily compiled out in production builds. - */ -int scsc_printk_tag(int force, int tag, const char *fmt, ...) -{ - int ret = 0, level = 0; - va_list args; - - /* Cannot use BINARY tag with strings logging */ - if (tag < NO_TAG || tag > MAX_TAG) - return ret; - level = get_debug_level(fmt); - if ((in_interrupt() && level >= scsc_droplevel_atomic)) - return ret; - va_start(args, fmt); - handle_klogbuf_out_string(level, NULL, tag, fmt, args, force); - va_end(args); - /* restart varargs */ - va_start(args, fmt); - ret = _scsc_printk(level, tag, fmt, args); - va_end(args); - return ret; -} -EXPORT_SYMBOL(scsc_printk_tag); - - -/** - * This is a variation on the main API that allows to specify loglevel - * by number. - */ -int scsc_printk_tag_lvl(int tag, int level, const char *fmt, ...) -{ - int ret = 0; - va_list args; - - /* Cannot use BINARY tag with strings logging */ - if (tag < NO_TAG || tag > MAX_TAG) - return ret; - if ((in_interrupt() && level >= scsc_droplevel_atomic)) - return ret; - va_start(args, fmt); - handle_klogbuf_out_string(level, NULL, tag, fmt, args, NO_FORCE_PRK); - va_end(args); - /* restart varargs */ - va_start(args, fmt); - ret = _scsc_printk(level, tag, fmt, args); - va_end(args); - return ret; -} -EXPORT_SYMBOL(scsc_printk_tag_lvl); - - -/** - * This is a variation on the main API that allows to specify a - * struct device reference. - */ -int scsc_printk_tag_dev(int force, int tag, struct device *dev, - const char *fmt, ...) -{ - int ret = 0, level = 0; - va_list args; - - /* Cannot use BINARY tag with strings logging */ - if (tag < NO_TAG || tag > MAX_TAG) - return ret; - level = get_debug_level(fmt); - if ((in_interrupt() && level >= scsc_droplevel_atomic)) - return ret; - va_start(args, fmt); - handle_klogbuf_out_string(level, dev, tag, fmt, args, force); - va_end(args); - /* restart varargs */ - va_start(args, fmt); - ret = _scsc_printk(level, tag, fmt, args); - va_end(args); - return ret; -} -EXPORT_SYMBOL(scsc_printk_tag_dev); - -/** - * This is a variation on the main API that allows to specify a - * struct device reference and an explicit numerical debug level. - */ -int scsc_printk_tag_dev_lvl(int force, int tag, struct device *dev, - int level, const char *fmt, ...) -{ - int ret = 0; - va_list args; - - /* Cannot use BINARY tag with strings logging */ - if (tag < NO_TAG || tag > MAX_TAG) - return ret; - if ((in_interrupt() && level >= scsc_droplevel_atomic)) - return ret; - va_start(args, fmt); - handle_klogbuf_out_string(level, dev, tag, fmt, args, force); - va_end(args); - /* restart varargs */ - va_start(args, fmt); - ret = _scsc_printk(level, tag, fmt, args); - va_end(args); - return ret; -} -EXPORT_SYMBOL(scsc_printk_tag_dev_lvl); - -/** - * This is a variation on the main API used to push binary blob into the ring. - */ -int scsc_printk_bin(int force, int tag, int dlev, const void *start, size_t len) -{ - int ret = 0; - - /* Cannot use NON BINARY tag with strings logging - * or NULLs start/len - */ - if (!start || !len || tag < FIRST_BIN_TAG || tag > LAST_BIN_TAG) - return ret; - dlev = (dlev >= 0) ? dlev : default_dbglevel; - if ((in_interrupt() && dlev >= scsc_droplevel_atomic)) - return ret; - handle_klogbuf_out_binary(dlev, tag, start, len, force); - /* consider proper tag droplevel */ - if (!initialized || !enable || !start || - (scsc_droplevel_all < 0 && *scsc_droplevels[tag] <= dlev) || - (scsc_droplevel_all >= 0 && scsc_droplevel_all <= dlev)) - return ret; - ret = push_record_blob(the_ringbuf, tag, dlev, - prepend_header, start, len); - return ret; -} -EXPORT_SYMBOL(scsc_printk_bin); - -/* - * This is a very basic mechanism to have implement the dynamic switch - * for one user (currently WLAN). If multiple users are - * required to use the dynamic logring switch, a new registration - * mechanism based on requests and use_count should be implemented to avoid one service - * re-enabling logring when some other has requested not to do so. - */ -int scsc_logring_enable(bool logging_enable) -{ - scsc_printk_tag(FORCE_PRK, NO_TAG, "scsc_logring %s\n", logging_enable ? "enable" : "disable"); - /* User has requested to disable logring */ - if (!logging_enable && enable) { - cached_enable = true; - enable = 0; - scsc_printk_tag(FORCE_PRK, NO_TAG, "Logring disabled\n"); - } else if (logging_enable && cached_enable) { - cached_enable = false; - enable = 1; - scsc_printk_tag(FORCE_PRK, NO_TAG, "Logring re-enabled\n"); - } else { - scsc_printk_tag(FORCE_PRK, NO_TAG, "Ignored\n"); - } - return 0; -} -EXPORT_SYMBOL(scsc_logring_enable); - - -MODULE_DESCRIPTION("SCSC Event Logger"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/misc/samsung/scsc/scsc_logring_main.h b/drivers/misc/samsung/scsc/scsc_logring_main.h deleted file mode 100644 index 85afd4e7b3a6..000000000000 --- a/drivers/misc/samsung/scsc/scsc_logring_main.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************** - * - * Copyright (c) 2016 - 2017 Samsung Electronics Co., Ltd. All rights reserved. - * - ********************************************************************************/ - -#ifndef _SCSC_LOGRING_MAIN_H_ -#define _SCSC_LOGRING_MAIN_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scsc_logring_common.h" - -#define ADD_DEBUG_MODULE_PARAM(tagname, default_level, filter) \ - int scsc_droplevel_ ## tagname = default_level; \ - module_param(scsc_droplevel_ ## tagname, int, S_IRUGO | S_IWUSR); \ - SCSC_MODPARAM_DESC(scsc_droplevel_ ## tagname, \ - "Droplevels for the '" # tagname "' family.", \ - "run-time", default_level) - -#define IS_PRINTK_REDIRECT_ALLOWED(ff, level, tag) \ - ((ff) == FORCE_PRK || \ - ((ff) != NO_ECHO_PRK && (level) < scsc_redirect_to_printk_droplvl)) - -#endif /* _SCSC_LOGRING_MAIN_H_ */ diff --git a/drivers/misc/samsung/scsc/scsc_logring_ring.c b/drivers/misc/samsung/scsc/scsc_logring_ring.c deleted file mode 100644 index 85d09e0bbf1a..000000000000 --- a/drivers/misc/samsung/scsc/scsc_logring_ring.c +++ /dev/null @@ -1,833 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016-2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#include "scsc_logring_ring.h" - -#ifdef CONFIG_SCSC_STATIC_RING_SIZE -static char a_ring[CONFIG_SCSC_STATIC_RING_SIZE + BASE_SPARE_SZ] __aligned(4); -#endif - -static int scsc_decode_binary_len = DEFAULT_BIN_DECODE_LEN; -module_param(scsc_decode_binary_len, int, S_IRUGO | S_IWUSR); -SCSC_MODPARAM_DESC(scsc_decode_binary_len, - "When reading a binary record dump these bytes-len in ASCII human readable form when reading", - "run-time", DEFAULT_BIN_DECODE_LEN); - -/* - * NOTE_CREATING_TAGS: when adding a tag string here REMEMBER to add - * it also where required, taking care to maintain the same ordering. - * (Search 4 NOTE_CREATING_TAGS) - */ -const char *tagstr[MAX_TAG + 1] = { - "binary", - "bin_wifi_ctrl_rx", - "bin_wifi_data_rx", - "bin_wifi_ctrl_tx", - "bin_wifi_data_tx", - "wlbt", /* this is the generic one...NO_TAG */ - "wifi_rx", - "wifi_tx", - "bt_common", - "bt_h4", - "bt_fw", - "bt_rx", - "bt_tx", - "cpktbuff", - "fw_load", - "fw_panic", - "gdb_trans", - "mif", - "clk20", - "clk20_test", - "fm", - "fm_test", - "mx_file", - "mx_fw", - "mx_sampler", - "mxlog_trans", - "mxman", - "mxman_test", - "mxmgt_trans", - "mx_mmap", - "mx_proc", - "panic_mon", - "pcie_mif", - "plat_mif", - "kic_common", - "wlbtd", - "wlog", - "lerna", - "mx_cfg", -#ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY - "init_deinit", - "netdev", - "cfg80211", - "mlme", - "summary_frames", - "hydra", - "tx", - "rx", - "udi", - "wifi_fcq", - "hip", - "hip_init_deinit", - "hip_fw_dl", - "hip_sdio_op", - "hip_ps", - "hip_th", - "hip_fh", - "hip_sig", - "func_trace", - "test", - "src_sink", - "fw_test", - "rx_ba", - "tdls", - "gscan", - "mbulk", - "flowc", - "smapper", -#endif - "test_me" -}; - -/** - * Calculate and returns the CRC32 for the provided record and record pos. - * Before calculating the CRC32 the crc field is temporarily substituted - * with the 32 LSB record relative starting position. - * Assumes the rec ptr area-validity has been checked upstream in the - * caller chain. - * We SKIP the fixed blob of the SYNC field that is placed ahead of - * CRC field. - * Assumes the related ring buffer is currently atomically accessed by - * caller. MUST NOT SLEEP. - */ -static inline uint32_t get_calculated_crc(struct scsc_ring_record *rec, - loff_t pos) -{ - uint32_t calculated_crc = 0; - uint32_t saved_crc = 0; - - saved_crc = rec->crc; - rec->crc = (uint32_t)pos; - /* we skip the fixed sync calculating crc */ - calculated_crc = - crc32_le(~0, (unsigned char const *)&rec->crc, - SCSC_CRC_RINGREC_SZ); - rec->crc = saved_crc; - return calculated_crc; -} - -/** - * Checks for record CRC sanity. - * Assumes the related ring buffer is currently atomically accessed by - * caller. MUST NOT SLEEP. - */ -static inline bool is_record_crc_valid(struct scsc_ring_record *rec, - loff_t pos) -{ - uint32_t calculated_crc = 0; - - calculated_crc = get_calculated_crc(rec, pos); - return calculated_crc == rec->crc; -} - -/** - * Calculate the proper CRC and set it into the crc field - * Assumes the related ring buffer is currently atomically accessed by - * caller. MUST NOT SLEEP. - */ -static inline void finalize_record_crc(struct scsc_ring_record *rec, - loff_t pos) -{ - uint32_t calculated_crc = 0; - - if (!rec) - return; - rec->crc = (uint32_t)pos; - calculated_crc = - crc32_le(~0, (unsigned char const *)&rec->crc, - SCSC_CRC_RINGREC_SZ); - rec->crc = calculated_crc; -} - -/** - * This function analyzes the pos provided relative to the provided - * ring, just to understand if it can be safely dereferenced. - * Assumes RING is already locked. - */ -static inline bool is_ring_pos_safe(struct scsc_ring_buffer *rb, - loff_t pos) -{ - if (!rb || pos > rb->bsz || pos < 0) - return false; - /* NOT Wrapped */ - if (rb->head > rb->tail && pos > rb->head) - return false; - /* Wrapped... */ - if (rb->head < rb->tail && - (pos > rb->head && pos < rb->tail)) - return false; - return true; -} - -/** - * This sanitizes record header before using it. - * It must be in the proper area related to head and tail and - * the CRC must fit the header. - */ -static inline bool is_ring_read_pos_valid(struct scsc_ring_buffer *rb, - loff_t pos) -{ - if (!is_ring_pos_safe(rb, pos)) - goto oos; - /* We do not check for SYNC before CRC since most of the time - * you are NOT OutOfSync and so you MUST check CRC anyway. - * It will be useful only for resync. - * At last...Check CRC ... doing this check LAST avoids the risk of - * dereferencing an already dangling pos pointer. - */ - if (!is_record_crc_valid(SCSC_GET_REC(rb, pos), pos)) - goto oos; - return true; -oos: - if (rb) - rb->oos++; - return false; -} - - -/** - * Buid a header into the provided buffer, - * and append the optional trail string - */ -static inline -int build_header(char *buf, int blen, struct scsc_ring_record *r, - const char *trail) -{ - int written = 0; - struct timeval tval = {}; - - tval = ns_to_timeval(r->nsec); - written = scnprintf(buf, blen, - "<%d>[%6lu.%06ld] [c%d] [%c] [%s] :: %s", - r->lev, tval.tv_sec, tval.tv_usec, - r->core, (char)r->ctx, tagstr[r->tag], - (trail) ? : ""); - return written; -} - - -/** - * We're going to overwrite something writing from the head toward the tail - * so we must search for the next tail far enough from head in oder not to be - * overwritten: that will be our new tail after the wrap over. - */ -static inline -loff_t find_next_tail_far_enough_from_start(struct scsc_ring_buffer *rb, - loff_t start, int len) -{ - loff_t new_tail = rb->tail; - - while (start + len >= new_tail && new_tail != rb->last) { - new_tail = SCSC_GET_NEXT_REC_ENTRY_POS(rb, new_tail); - rb->records--; - } - if (start + len >= new_tail) { - new_tail = 0; - rb->records--; - } - return new_tail; -} - -/** - * This handles the just plain append of a record to head without - * any need of wrapping or overwriting current tail - * You can provide two buffer here: the second, hbuf, is optional - * and will be written first. This is to account for the binary case - * in which the record data are written at first into the spare area - * (like we do with var strings, BUT then the bulk of binary data is - * written directly in place into the ring without double copies. - */ -static inline -void scsc_ring_buffer_plain_append(struct scsc_ring_buffer *rb, - const char *srcbuf, int slen, - const char *hbuf, int hlen) -{ - /* empty condition is special case */ - if (rb->records) - rb->head += SCSC_GET_SLOT_LEN(rb, rb->head); - if (hbuf) - memcpy(SCSC_GET_HEAD_PTR(rb), hbuf, hlen); - else - hlen = 0; - memcpy(SCSC_GET_HEAD_PTR(rb) + hlen, srcbuf, slen); - finalize_record_crc((struct scsc_ring_record *)SCSC_GET_HEAD_PTR(rb), - rb->head); - rb->records++; - if (rb->head > rb->last) - rb->last = rb->head; -} - - -/** - * This handles the case in which appending current record must account - * for overwriting: this sitiation can happen at the end of ring if we do NOT - * have enough space for the current record, or in any place when the buffer - * has wrapped, head is before tail and there's not enough space to write - * between current head and tail. - */ -static inline -void scsc_ring_buffer_overlap_append(struct scsc_ring_buffer *rb, - const char *srcbuf, int slen, - const char *hbuf, int hlen) -{ - if (rb->head < rb->tail && - slen + hlen < rb->bsz - SCSC_GET_NEXT_SLOT_POS(rb, rb->head)) - rb->head += SCSC_GET_SLOT_LEN(rb, rb->head); - else { - rb->last = rb->head; - rb->head = 0; - rb->tail = 0; - rb->wraps++; - } - rb->tail = - find_next_tail_far_enough_from_start(rb, rb->head, slen + hlen); - if (hbuf) - memcpy(SCSC_GET_HEAD_PTR(rb), hbuf, hlen); - else - hlen = 0; - memcpy(SCSC_GET_HEAD_PTR(rb) + hlen, srcbuf, slen); - finalize_record_crc((struct scsc_ring_record *)SCSC_GET_HEAD_PTR(rb), - rb->head); - rb->records++; - if (rb->head > rb->last) - rb->last = rb->head; -} - - -/** - * This uses the spare area to prepare the record descriptor and to expand - * the format string into the spare area in order to get the final lenght of - * the whole record+data. Data is pre-pended with a header representing the - * data hold in binary form in the record descriptor. - * This data duplication helps when we'll read back a record holding string - * data, we won't have to build the header on the fly during the read. - */ -static inline -int tag_writer_string(char *spare, int tag, int lev, - int prepend_header, const char *msg_head, va_list args) -{ - int written; - char bheader[SCSC_HBUF_LEN] = {}; - struct scsc_ring_record *rrec; - - /* Fill record in place */ - rrec = (struct scsc_ring_record *)spare; - SCSC_FILL_RING_RECORD(rrec, tag, lev); - if (prepend_header) - build_header(bheader, SCSC_HBUF_LEN, rrec, NULL); - written = scnprintf(SCSC_GET_REC_BUF(spare), - BASE_SPARE_SZ - SCSC_RINGREC_SZ, "%s", bheader); - /** - * NOTE THAT - * --------- - * vscnprintf retvalue is the number of characters which have been - * written into the @buf NOT including the trailing '\0'. - * If @size is == 0 the function returns 0. - * Here we enforce a line lenght limit equal to - * BASE_SPARE_SZ - SCSC_RINGREC_SZ. - */ - written += vscnprintf(SCSC_GET_REC_BUF(spare) + written, - BASE_SPARE_SZ - SCSC_RINGREC_SZ - written, - msg_head, args); - /* complete record metadata */ - rrec->len = written; - return written; -} - -/** - * A ring API function to push variable length format string into the buffer - * After the record has been created and pushed into the ring any process - * waiting on the related waiting queue is awakened. - */ -int push_record_string(struct scsc_ring_buffer *rb, int tag, int lev, - int prepend_header, const char *msg_head, va_list args) -{ - int rec_len = 0; - loff_t free_bytes; - unsigned long flags; - - /* Prepare ring_record and header if needed */ - raw_spin_lock_irqsave(&rb->lock, flags); - rec_len = tag_writer_string(rb->spare, tag, lev, prepend_header, - msg_head, args); - /* Line too long anyway drop */ - if (rec_len >= BASE_SPARE_SZ - SCSC_RINGREC_SZ) { - raw_spin_unlock_irqrestore(&rb->lock, flags); - return 0; - } - free_bytes = SCSC_RING_FREE_BYTES(rb); - /** - * Evaluate if it's a trivial append or if we must account for - * any overwrap. Note that we do NOT truncate record across ring - * boundaries, if a record does NOT fit at the end of buffer, - * we'll write it from start directly. - */ - if (rec_len + SCSC_RINGREC_SZ < free_bytes) - scsc_ring_buffer_plain_append(rb, rb->spare, - SCSC_RINGREC_SZ + rec_len, - NULL, 0); - else - scsc_ring_buffer_overlap_append(rb, rb->spare, - SCSC_RINGREC_SZ + rec_len, - NULL, 0); - rb->written += rec_len; - raw_spin_unlock_irqrestore(&rb->lock, flags); - /* WAKEUP EVERYONE WAITING ON THIS BUFFER */ - wake_up_interruptible(&rb->wq); - return rec_len; -} - -/* This simply builds up a record descriptor for a binary entry. */ -static inline -int tag_writer_binary(char *spare, int tag, int lev, size_t hexlen) -{ - struct scsc_ring_record *rrec; - - rrec = (struct scsc_ring_record *)spare; - SCSC_FILL_RING_RECORD(rrec, tag, lev); - rrec->len = hexlen; - - return hexlen; -} - -/** - * A ring API function to push binary data into the ring buffer. Binary data - * is copied from the start/len specified location. - * After the record has been created and pushed into the ring any process - * waiting on the related waiting queue is awakened. - */ -int push_record_blob(struct scsc_ring_buffer *rb, int tag, int lev, - int prepend_header, const void *start, size_t len) -{ - loff_t free_bytes; - unsigned long flags; - - if (len > SCSC_MAX_BIN_BLOB_SZ) - len = SCSC_MAX_BIN_BLOB_SZ; - /* Prepare ring_record and header if needed */ - raw_spin_lock_irqsave(&rb->lock, flags); - memset(rb->spare, 0x00, rb->ssz); - tag_writer_binary(rb->spare, tag, lev, len); - free_bytes = SCSC_RING_FREE_BYTES(rb); - if (len + SCSC_RINGREC_SZ < free_bytes) - scsc_ring_buffer_plain_append(rb, start, len, - rb->spare, SCSC_RINGREC_SZ); - else - scsc_ring_buffer_overlap_append(rb, start, len, - rb->spare, SCSC_RINGREC_SZ); - rb->written += len; - raw_spin_unlock_irqrestore(&rb->lock, flags); - /* WAKEUP EVERYONE WAITING ON THIS BUFFER */ - wake_up_interruptible(&rb->wq); - return len; -} - -/* A simple reader used to retrieve a string from the record - * It always return ONE WHOLE RECORD if it fits the provided tbuf OR NOTHING. - */ -static inline -size_t tag_reader_string(char *tbuf, struct scsc_ring_buffer *rb, - int start_rec, size_t tsz) -{ - size_t max_chunk = SCSC_GET_REC_LEN(SCSC_GET_PTR(rb, start_rec)); - - if (max_chunk <= tsz) - memcpy(tbuf, SCSC_GET_REC_BUF(rb->buf + start_rec), max_chunk); - else - max_chunk = 0; - return max_chunk; -} - -/* - * Helper to dump binary data in ASCII readable form up to - * scsc_decode_binary_len bytes: when such modparam is set to -1 - * this will dump all the available data. Data is dumped onto the - * output buffer with an endianity that conforms to the data as - * dumped by the print_hex_dump() kernel standard facility. - */ -static inline -int binary_hexdump(char *tbuf, int tsz, struct scsc_ring_record *rrec, - int start, int dlen) -{ - int i, j, bytepos; - unsigned char *blob = SCSC_GET_REC_BUF(rrec); - char *hmap = "0123456789abcdef"; - - /** - * Scan the buffer reversing endianity when appropriate and - * producing ASCII human readable output while obeying chosen - * maximum decoden_len dlen. - */ - for (j = start, i = 0; j < tsz && i < rrec->len && i < dlen; i += 4) { - bytepos = (rrec->len - i - 1 >= 3) ? 3 : rrec->len - i - 1; - /* Reverse endianity to little only on 4-byte boundary */ - if (bytepos == 3) { - for (; bytepos >= 0; bytepos--) { - if (i + bytepos >= dlen) - continue; - tbuf[j++] = hmap[blob[i + bytepos] >> 4 & 0x0f]; - tbuf[j++] = hmap[blob[i + bytepos] & 0x0f]; - } - } else { - int bb; - - /** - * Trailing bytes NOT aligned on a 4-byte boundary - * should be decoded maintaining the original endianity. - * This way we obtain a binary output perfectly equal - * to the one generated by the original UDI tools. - */ - for (bb = 0; bb <= bytepos; bb++) { - if (i + bb >= dlen) - break; - tbuf[j++] = hmap[blob[i + bb] >> 4 & 0x0f]; - tbuf[j++] = hmap[blob[i + bb] & 0x0f]; - } - } - } - return j; -} - -/** - * A reader used to dump binary records: this function first of all - * builds a proper human readable header to identify the record with the - * usual debuglevel and timestamps and then DUMPS some of the binary blob - * in ASCII human readable form: how much is dumped depends on the module - * param scsc_decode_binary_len (default 8 bytes). - * ANYWAY ONLY ONE WHOLE RECORD IS DUMPED OR NOTHING IF IT DOES NOT FIT - * THE PROVIDED DESTINATION BUFFER TBUF. - */ -static inline -size_t tag_reader_binary(char *tbuf, struct scsc_ring_buffer *rb, - int start_rec, size_t tsz) -{ - size_t written; - int declen = scsc_decode_binary_len; - struct scsc_ring_record *rrec; - char bheader[SCSC_HBUF_LEN] = {}; - char binfo[SCSC_BINFO_LEN] = {}; - size_t max_chunk; - - rrec = (struct scsc_ring_record *)SCSC_GET_PTR(rb, start_rec); - if (declen < 0 || declen > rrec->len) - declen = rrec->len; - if (declen) - snprintf(binfo, SCSC_BINFO_LEN, "HEX[%d/%d]: ", - declen, rrec->len); - written = build_header(bheader, SCSC_HBUF_LEN, rrec, - declen ? binfo : ""); - /* Account for byte decoding: two ASCII char for each byte */ - max_chunk = written + (declen * 2); - if (max_chunk <= tsz) { - memcpy(tbuf, bheader, written); - if (declen) - written = binary_hexdump(tbuf, tsz - written, - rrec, written, declen); - tbuf[written] = '\n'; - written++; - } else { - written = 0; - } - return written; -} - -/** - * This is a utility function to read from the specified ring_buffer - * up to 'tsz' amount of data starting from position record 'start_rec'. - * This function reads ONLY UP TO ONE RECORD and returns the effective - * amount of data bytes read; it invokes the proper tag_reader_* helper - * depending on the specific record is handling. - * Data is copied to a TEMP BUFFER provided by user of this function, - * IF AND ONLY IF a whole record CAN fit into the space available in the - * destination buffer, otherwise record is NOT copied and 0 is returned. - * This function DOES NOT SLEEP. - * Caller IS IN CHARGE to SOLVE any sync issue on provided tbuf and - * underlying ring buffer. - * - * @tbuf: a temp buffer destination for the read data - * @rb: the ring_buffer to use. - * @start_rec: the record from which to start expressed as a record - * starting position. - * @tsz: the available space in tbuf - * @return size_t: returns the bytes effectively read. - */ -static inline size_t -_read_one_whole_record(void *tbuf, struct scsc_ring_buffer *rb, - int start_rec, size_t tsz) -{ - if (SCSC_GET_REC_TAG(SCSC_GET_PTR(rb, start_rec)) > LAST_BIN_TAG) - return tag_reader_string(tbuf, rb, start_rec, tsz); - else - return tag_reader_binary(tbuf, rb, start_rec, tsz); -} - - -/** - * This just inject a string into the buffer to signal we've gone - * OUT OF SYNC due to Ring WRAPPING too FAST, noting how many bytes - * we resynced. - */ -static inline size_t mark_out_of_sync(char *tbuf, size_t tsz, - int resynced_bytes) -{ - size_t written = 0; - struct timeval tval = {}; - - tval = ns_to_timeval(local_clock()); - /* We should write something even if truncated ... */ - written = scnprintf(tbuf, tsz, - "<7>[%6lu.%06ld] [c%d] [P] [OOS] :: [[[ OUT OF SYNC -- RESYNC'ED BYTES %d ]]]\n", - tval.tv_sec, tval.tv_usec, smp_processor_id(), - resynced_bytes); - return written; -} - -/** - * Attempt resync searching for SYNC pattern and verifying CRC. - * ASSUMES that the invalid_pos provided is anyway safe to access, since - * it should be checked by the caller in advance. - * The amount of resynced bytes are not necessarily the number of bytes - * effectively lost....they could be much more...imagine the ring had - * overwrap multiple times before detecting OUT OF SYNC. - */ -static inline loff_t reader_resync(struct scsc_ring_buffer *rb, - loff_t invalid_pos, int *resynced_bytes) -{ - int bytes = 0; - loff_t sync_pos = rb->head; - struct scsc_ring_record *candidate = SCSC_GET_REC(rb, invalid_pos); - - *resynced_bytes = 0; - /* Walking thorugh the ring in search of the sync one byte at time */ - while (invalid_pos != rb->head && - !SCSC_IS_REC_SYNC_VALID(candidate)) { - invalid_pos = (invalid_pos < rb->last) ? - (invalid_pos + sizeof(u8)) : 0; - bytes += sizeof(u8); - candidate = SCSC_GET_REC(rb, invalid_pos); - } - if (invalid_pos == rb->head || - (SCSC_IS_REC_SYNC_VALID(candidate) && - is_record_crc_valid(candidate, invalid_pos))) { - sync_pos = invalid_pos; - *resynced_bytes = bytes; - } - return sync_pos; -} - -/** - * An Internal API ring function to retrieve into the provided tbuf - * up to N WHOLE RECORDS starting from *next_rec. - * It STOPS collecting records if: - * - NO MORE RECORDS TO READ: last_read_record record is head - * - NO MORE SPACE: on provided destination tbuf to collect - * one more WHOLE record - * - MAX NUMBER OF REQUIRED RECORDS READ: if max_recs was passed in - * as ZERO it means read as much as you can till head is reached. - * - * If at start it detects and OUT OF SYNC, so that next_rec is - * NO MORE pointing to a valid record, it tries to RE-SYNC on next - * GOOD KNOWN record or to HEAD as last resource and injects into - * the user buffer an OUT OF SYNC marker record. - * - * ASSUMES proper locking and syncing ALREADY inplace...does NOT SLEEP. - */ -size_t read_next_records(struct scsc_ring_buffer *rb, int max_recs, - loff_t *last_read_rec, void *tbuf, size_t tsz) -{ - size_t bytes_read = 0, last_read = -1; - int resynced_bytes = 0, records = 0; - loff_t next_rec = 0; - - /* Nothing to read...simply return 0 causing reader to exit */ - if (*last_read_rec == rb->head) - return bytes_read; - if (!is_ring_read_pos_valid(rb, *last_read_rec)) { - if (is_ring_pos_safe(rb, *last_read_rec)) { - /* Try to resync from *last_read_rec INVALID POS */ - next_rec = reader_resync(rb, *last_read_rec, - &resynced_bytes); - } else { - /* Skip to head...ONLY safe place known in tis case. */ - resynced_bytes = 0; - next_rec = rb->head; - } - bytes_read += mark_out_of_sync(tbuf, tsz, resynced_bytes); - } else { - /* next to read....we're surely NOT already at rb->head here */ - next_rec = (*last_read_rec != rb->last) ? - SCSC_GET_NEXT_SLOT_POS(rb, *last_read_rec) : 0; - } - do { - /* Account for last read */ - last_read = bytes_read; - bytes_read += - _read_one_whole_record(tbuf + bytes_read, rb, - next_rec, tsz - bytes_read); - /* Did a WHOLE record fit into available tbuf ? */ - if (bytes_read != last_read) { - records++; - *last_read_rec = next_rec; - if (*last_read_rec != rb->head) - next_rec = (next_rec != rb->last) ? - SCSC_GET_NEXT_SLOT_POS(rb, next_rec) : 0; - } - } while (*last_read_rec != rb->head && - last_read != bytes_read && - (!max_recs || records <= max_recs)); - - return bytes_read; -} - -/** - * This function returns a static snapshot of the ring that can be used - * for further processing using usual records operations. - * - * It returns a freshly allocated scsc_ring_buffer descriptor whose - * internal references are exactly the same as the original buffer - * being snapshot, and with all the sync machinery re-initialized. - * Even if the current use-case does NOT make any use of spinlocks and - * waitqueues in the snapshot image, we provide an initialized instance - * in order to be safe for future (mis-)usage. - * - * It also takes care to copy the content of original ring buffer into - * the new snapshot image (including the spare area) using the provided - * pre-allocated snap_buf. - * - * Assumes ring is already spinlocked. - * - * @rb: the original buffer to snapshot - * @snap_buf: the pre-allocated ring-buffer area to use for copying records - * @snap_sz: pre-allocated area including spare - * @snap_name: a human readable descriptor - */ -struct scsc_ring_buffer *scsc_ring_get_snapshot(const struct scsc_ring_buffer *rb, - void *snap_buf, size_t snap_sz, - char *snap_name) -{ - struct scsc_ring_buffer *snap_rb = NULL; - - if (!rb || !snap_buf || !snap_name || snap_sz != rb->bsz + rb->ssz) - return snap_rb; - - /* Here we hold a lock starving writers...try to be quick using - * GFP_ATOMIC since scsc_ring_buffer is small enough (144 bytes) - */ - snap_rb = kzalloc(sizeof(*rb), GFP_ATOMIC); - if (!snap_rb) - return snap_rb; - - /* Copy original buffer content on provided snap_buf */ - if (memcpy(snap_buf, rb->buf, snap_sz)) { - snap_rb->bsz = rb->bsz; - snap_rb->ssz = rb->ssz; - snap_rb->head = rb->head; - snap_rb->tail = rb->tail; - snap_rb->last = rb->last; - snap_rb->written = rb->written; - snap_rb->records = rb->records; - snap_rb->wraps = rb->wraps; - /* this is related to reads so must be re-init */ - snap_rb->oos = 0; - strncpy(snap_rb->name, snap_name, RNAME_SZ - 1); - /* Link the copies */ - snap_rb->buf = snap_buf; - snap_rb->spare = snap_rb->buf + snap_rb->bsz; - /* cleanup spare */ - memset(snap_rb->spare, 0x00, snap_rb->ssz); - /* Re-init snapshot copies of sync tools */ - raw_spin_lock_init(&snap_rb->lock); - init_waitqueue_head(&snap_rb->wq); - } else { - kfree(snap_rb); - snap_rb = NULL; - } - - return snap_rb; -} - -/* Assumes ring is already spinlocked. */ -void scsc_ring_truncate(struct scsc_ring_buffer *rb) -{ - rb->head = 0; - rb->tail = 0; - rb->records = 0; - rb->written = 0; - rb->wraps = 0; - rb->last = 0; - memset(rb->buf + rb->head, 0x00, SCSC_RINGREC_SZ); -} - -/** - * alloc_ring_buffer - Allocates and initializes a basic ring buffer, - * including a basic spare area where to handle strings-splitting when - * buffer wraps. Basic spinlock/mutex init takes place here too. - * - * @bsz: the size of the ring buffer to allocate in bytes - * @ssz: the size of the spare area to allocate in bytes - * @name: a name for this ring buffer - */ -struct scsc_ring_buffer __init *alloc_ring_buffer(size_t bsz, size_t ssz, - const char *name) -{ - struct scsc_ring_buffer *rb = kmalloc(sizeof(*rb), GFP_KERNEL); - - if (!rb) - return NULL; - rb->bsz = bsz; - rb->ssz = ssz; -#ifndef CONFIG_SCSC_STATIC_RING_SIZE - rb->buf = kzalloc(rb->bsz + rb->ssz, GFP_KERNEL); - if (!rb->buf) { - kfree(rb); - return NULL; - } -#else - rb->buf = a_ring; -#endif - rb->head = 0; - rb->tail = 0; - rb->last = 0; - rb->written = 0; - rb->records = 0; - rb->wraps = 0; - rb->oos = 0; - rb->spare = rb->buf + rb->bsz; - memset(rb->name, 0x00, RNAME_SZ); - strncpy(rb->name, name, RNAME_SZ - 1); - raw_spin_lock_init(&rb->lock); - init_waitqueue_head(&rb->wq); - - return rb; -} - -/* - * free_ring_buffer - Free the ring what else... - * ...does NOT account for spinlocks existence currently - * - * @rb: a pointer to the ring buffer to free - */ -void free_ring_buffer(struct scsc_ring_buffer *rb) -{ - if (!rb) - return; -#ifndef CONFIG_SCSC_STATIC_RING_SIZE - kfree(rb->buf); -#endif - kfree(rb); -} diff --git a/drivers/misc/samsung/scsc/scsc_logring_ring.h b/drivers/misc/samsung/scsc/scsc_logring_ring.h deleted file mode 100644 index 5d230b5f0bb2..000000000000 --- a/drivers/misc/samsung/scsc/scsc_logring_ring.h +++ /dev/null @@ -1,244 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ - -#ifndef _SCSC_LOGRING_RING_H_ -#define _SCSC_LOGRING_RING_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "scsc_logring_common.h" - -#define SCSC_BINFO_LEN 32 -#define SCSC_HBUF_LEN 128 -/* A safe size to enforce on ingressing binary blobs; this accounts - * for possible binary expansion while reading, in order to fit the reader - * DEFAULT_TBUF_SZ in any possible case: this way we avoid to have truncated - * data also on read while dumping big binary blobs. - */ -#define SCSC_MAX_BIN_BLOB_SZ 1920 -/** - * This spare area is used to prepare a logging entry before pushing it into - * the ring and so it's the maximum length allowed for a log entry. - * When this change (hugely) you should check the size of len field - * in the following struct scsc_ring_record. - */ -#define BASE_SPARE_SZ 2048 -#define RNAME_SZ 16 -#define DEFAULT_RING_BUFFER_SZ 1048576 -#define DEFAULT_ENABLE_HEADER 1 -#define DEFAULT_ENABLE_LOGRING 1 -/* The default len, in bytes, of the binary blob to decode in ASCII - * Human readable form. -1 means DECODE EVERYTHING ! - */ -#define DEFAULT_BIN_DECODE_LEN -1 -#define DEBUGFS_ROOT "/sys/kernel/debug" -#define DEBUGFS_RING0_ROOT "ring0" - -/** - * Our ring buffer is allocated simply as a bunch of contiguos bytes. - * Data is stored as a contiguos stream of concatenated records, each one - * starting with a record descriptor of type scsc_ring_record: data content - * is then appended to the record descriptor; in this way we can account - * for different types of content, pushing the TAG describing the content - * into the record descriptor itself, being then able to operate differently - * on read depending on the type of content. - * The tail and head references 'points' to the start of the first (oldest) - * and the last (newest) record: any write will happen after the end - * of the current head: these references in fact points to the starting byte - * of the record descriptor modulus the ring size (they're NOT abosolute - * pointers). Since our 'metadata' is embedded inside the ring itself (like - * printk does) we never write variable string content in place BUT use - * instead the spare area (allocated contiguosly at the end of the ring) - * to expand the provided format string and then memcpy the content to - * the final position after having properly updated the record descriptors - * and eventually moved away the tail when overwriting. - * Moreover we never wrap a record across the ring boundary: if there's NOT - * enough space at the end of the ring, we simply place it at the start. - * Moreover this structs holds a kcache reference to allocate temporary - * buffers to use when double buffering is needed, a spinlock_t for - * protection and a wait_queue_t for blocking I/O. - * - * @buf: the ring-buffer itself starts here - * @spare: start of spare area (buf[bsz]) - * @name: a simple named identifier - * @bsz: ring size - * @ssz: size of spare (fixed at BASE_SPARE_SZ) - * @head: newest record written (first byte)...next write after it - * @tail: odelst record written (first byte)...full dump read will start - * from here - * @last: the last record before the end of the ring. - * @records: the number of records - * @written: a general progressive counter of total bytes written into - * the ring - * @lock: a spinlock_t to protetc concurrent access - * @wq: a wait queue where to put sleeping processes waiting for input. - * They're woken up at the end os scsc_printk(). - * @refc: a reference counter...currently unused. - * @private: useful to hold some user provided data (used to hold debugfs - * initdata related to this ring) - * @kcache: a reference to a kmem_cache created at initialization time - * to get fresh temporary buffers on the fly when copying to user and in - * need of a double buffer - */ -struct scsc_ring_buffer { - char *buf; - char *spare; - char name[RNAME_SZ]; - size_t bsz; - size_t ssz; - loff_t head; - loff_t tail; - loff_t last; - int records; - int wraps; - int oos; - u64 written; - raw_spinlock_t lock; - wait_queue_head_t wq; - atomic_t refc; - void *private; -}; - -/** - * Our ring buffer is now built concatenating entries prepended by a record - * that describes the content itself. This will allow us to store different - * types of data (NOT only string) and to interpret it. - * Each record is described by this struct that is laid out in front of the - * effective content: - * - * | SYNC | CRC | tag | len | lev | ctx | core | nsec | sync = SYNC_MAGIC; \ - (r)->crc = 0; \ - (r)->nsec = local_clock(); \ - (r)->tag = tag; \ - (r)->len = 0; \ - (r)->lev = lev; \ - (r)->ctx = ((in_interrupt()) ? \ - ((in_softirq()) ? 'S' : 'I') : 'P'); \ - (r)->core = smp_processor_id(); \ - } while (0) - - -#define SCSC_RINGREC_SZ (sizeof(struct scsc_ring_record)) -#define SCSC_CRC_RINGREC_SZ (SCSC_RINGREC_SZ - sizeof(SYNC_MAGIC)) - -#define SCSC_IS_RING_IN_USE(ring) \ - ((atomic_read(&((struct scsc_ring_buffer *)(ring))->refc)) != 0) - -#define SCSC_GET_RING_REFC(ring) \ - atomic_inc(&((struct scsc_ring_buffer *)(ring))->refc) - -#define SCSC_PUT_RING_REFC(ring) \ - atomic_dec(&((struct scsc_ring_buffer *)(ring))->refc) - - -#define SCSC_GET_REC_BUF(p) (((char *)(p)) + SCSC_RINGREC_SZ) - -#define SCSC_GET_REC_LEN(recp) (((struct scsc_ring_record *)(recp))->len) - -#define SCSC_GET_REC_TAG(recp) (((struct scsc_ring_record *)(recp))->tag) - -#define SCSC_GET_REC_CRC(recp) (((struct scsc_ring_record *)(recp))->crc) - -#define SCSC_GET_PTR(ring, pos) ((ring)->buf + (pos)) - -#define SCSC_GET_REC(ring, pos) \ - ((struct scsc_ring_record *)(SCSC_GET_PTR((ring), (pos)))) - -#define SCSC_IS_REC_SYNC_VALID(recp) ((recp)->sync == SYNC_MAGIC) - -#define SCSC_GET_HEAD_PTR(ring) SCSC_GET_PTR((ring), (ring)->head) - -#define SCSC_GET_NEXT_FREE_SLOT_PTR(ring) \ - (SCSC_GET_HEAD_PTR((ring)) + SCSC_RINGREC_SZ + \ - SCSC_GET_REC_LEN(SCSC_GET_HEAD_PTR(ring))) - -#define SCSC_GET_SLOT_LEN(ring, pos) \ - (((SCSC_GET_REC_LEN(SCSC_GET_PTR((ring), (pos)))) != 0) ? \ - (SCSC_RINGREC_SZ + SCSC_GET_REC_LEN(SCSC_GET_PTR((ring), (pos)))) : 0) - -#define SCSC_GET_NEXT_SLOT_POS(ring, pos) \ - ((pos) + SCSC_GET_SLOT_LEN((ring), (pos))) - -#define SCSC_RING_FREE_BYTES(rb) \ - (((rb)->head >= (rb)->tail) ? \ - ((rb)->bsz - SCSC_GET_NEXT_SLOT_POS(rb, rb->head)) : \ - ((rb)->tail - SCSC_GET_NEXT_SLOT_POS(rb, rb->head))) - -#define SCSC_USED_BYTES(rb) ((rb)->bsz - SCSC_RING_FREE_BYTES(rb)) - -#define SCSC_LOGGED_BYTES(rb) (SCSC_USED_BYTES(rb) - \ - ((rb)->records * SCSC_RINGREC_SZ)) - -#define SCSC_GET_NEXT_REC_ENTRY_POS(ring, rpos) \ - (rpos + SCSC_RINGREC_SZ + \ - SCSC_GET_REC_LEN(SCSC_GET_PTR((ring), (rpos)))) - -/* Ring buffer API */ -struct scsc_ring_buffer *alloc_ring_buffer(size_t bsz, size_t ssz, - const char *name) __init; -void free_ring_buffer(struct scsc_ring_buffer *rb); -void scsc_ring_truncate(struct scsc_ring_buffer *rb); -int push_record_string(struct scsc_ring_buffer *rb, int tag, int lev, - int prepend_header, const char *msg_head, va_list args); -int push_record_blob(struct scsc_ring_buffer *rb, int tag, int lev, - int prepend_header, const void *start, size_t len); -size_t read_next_records(struct scsc_ring_buffer *rb, int max_recs, - loff_t *last_read_rec, void *tbuf, size_t tsz); -struct scsc_ring_buffer *scsc_ring_get_snapshot(const struct scsc_ring_buffer *rb, - void *snap_buf, size_t snap_sz, - char *snap_name); -#endif /* _SCSC_LOGRING_RING_H_ */ diff --git a/drivers/misc/samsung/scsc/scsc_loopback.c b/drivers/misc/samsung/scsc/scsc_loopback.c deleted file mode 100644 index 27f7072edca3..000000000000 --- a/drivers/misc/samsung/scsc/scsc_loopback.c +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Loopback Protocol (Implementation) - */ - -#include -#include - -#include - -#include "scsc_loopback.h" - -/*****************************************************************************/ - -/** - * Handle data received on port by sending it back. - */ -static void scsc_loopback_port_recv( - struct scsc_mport *port, - const unsigned char *data, - size_t count) -{ - os_trace_dbg("%s: @%p, count %zu", __func__, port, count); - - scsc_mport_emit(port, data, count); -} - -static const struct scsc_mport_ops scsc_loopback_port_ops = { - scsc_loopback_port_recv -}; - -/*****************************************************************************/ - -void scsc_loopback_init(struct scsc_loopback *loopback) -{ - os_trace_dbg("%s: @%p", __func__, loopback); - - scsc_mport_init(&loopback->port, &scsc_loopback_port_ops); -} - -void scsc_loopback_deinit(struct scsc_loopback *loopback) -{ -} - -struct scsc_mport *scsc_loopback_get_port( - struct scsc_loopback *loopback) -{ - return &loopback->port; -} diff --git a/drivers/misc/samsung/scsc/scsc_loopback.h b/drivers/misc/samsung/scsc/scsc_loopback.h deleted file mode 100644 index 10ddf67c069f..000000000000 --- a/drivers/misc/samsung/scsc/scsc_loopback.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __HCI_LOOPBACK_H -#define __HCI_LOOPBACK_H -/** - * Loopback Protocol (Interface) - * - * Bounces anything send straight back. - */ - -#include "scsc_mport.h" - -/*****************************************************************************/ - -struct scsc_loopback { - struct scsc_mport port; -}; - -/*****************************************************************************/ - -void scsc_loopback_init(struct scsc_loopback *loopback); -void scsc_loopback_deinit(struct scsc_loopback *loopback); - -struct scsc_mport *scsc_loopback_get_port(struct scsc_loopback *loopback); - -#endif /* __HCI_LOOPBACK_H */ diff --git a/drivers/misc/samsung/scsc/scsc_mif_abs.h b/drivers/misc/samsung/scsc/scsc_mif_abs.h deleted file mode 100644 index 3f40635e8c0c..000000000000 --- a/drivers/misc/samsung/scsc/scsc_mif_abs.h +++ /dev/null @@ -1,234 +0,0 @@ -/**************************************************************************** -* -* Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved -* -****************************************************************************/ - -#ifndef __SCSC_MIF_ABS_H -#define __SCSC_MIF_ABS_H - -#ifdef CONFIG_SCSC_QOS -#include -#endif -#include -#include -#include - -struct device; - -/* To R4/M4 */ -enum scsc_mif_abs_target { - SCSC_MIF_ABS_TARGET_R4 = 0, - SCSC_MIF_ABS_TARGET_M4 = 1, -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - SCSC_MIF_ABS_TARGET_M4_1 = 2 -#endif -}; - -#ifdef CONFIG_SCSC_SMAPPER -#define SCSC_MIF_SMAPPER_MAX_BANKS 32 - -struct scsc_mif_smapper_info { - u32 num_entries; - u32 mem_range_bytes; -}; - -enum scsc_mif_abs_bank_type { - SCSC_MIF_ABS_NO_BANK = 0, - SCSC_MIF_ABS_SMALL_BANK = 1, - SCSC_MIF_ABS_LARGE_BANK = 2 -}; -#endif - -#ifdef CONFIG_SCSC_QOS -struct scsc_mifqos_request { - struct pm_qos_request pm_qos_req_mif; - struct pm_qos_request pm_qos_req_int; - struct pm_qos_request pm_qos_req_cl0; - struct pm_qos_request pm_qos_req_cl1; -}; -#endif - -#define SCSC_REG_READ_WLBT_STAT 0 - -/** - * Abstraction of the Maxwell "Memory Interface" aka MIF. - * - * There will be at least two implementations of this - * interface - The native AXI one and a PCIe based emulation. - * - * A reference to an interface will be passed to the - * scsc_mx driver when the system startsup. - */ -struct scsc_mif_abs { -/** - * Destroy this interface. - * - * This should be called when the underlying device is - * removed. - */ - void (*destroy)(struct scsc_mif_abs *interface); - /* Return an unique id for this host, and prefreabrly identifies specific device (example pcie0, pcie1) */ - char *(*get_uid)(struct scsc_mif_abs *interface); -/** - * Controls the hardware "reset" state of the Maxwell - * subsystem. - * - * Setting reset=TRUE places the subsystem in its low - * power "reset" state. This function is called - * by the Maxwell Manager near the end of the subsystem - * shutdown process, before "unmapping" the interface. - * - * Setting reset=FALSE release the subsystem reset state. - * The subystem will then start its cold boot sequence. This - * function is called - * by the Subsystem Manager near the end of the subsystem - * startup process after installing the maxwell firmware and - * other resources in MIF RAM. - */ - int (*reset)(struct scsc_mif_abs *interface, bool reset); -/** - * This function maps the Maxwell interface hardware (MIF - * DRAM) into kernel memory space. - * - * Amount of memory allocated must be defined and returned - * on (*allocated) by the abstraction layer implemenation. - * - * This returns kernel-space pointer to the start of the - * shared MIF DRAM. The Maxwell Manager will load firmware - * to this location and configure the MIF Heap Manager to - * manage any unused memory at the end of the DRAM region. - * - * The scsc_mx driver should call this when the Maxwell - * subsystem is required by any service client. - * - * The mailbox, irq and dram functions are only usable once - * this call has returned. HERE: Should we rename this to - * "open" and return a handle to these conditional methods? - */ - void *(*map)(struct scsc_mif_abs *interface, size_t *allocated); -/** - * The inverse of "map". Should be called once the maxwell - * subsystem is no longer required and has been placed into - * "reset" state (see reset method). - */ - void (*unmap)(struct scsc_mif_abs *interface, void *mem); - -/** - * The Mailbox pointer returned can be used for direct access - * to the hardware register for efficiency. - * The pointer is guaranteed to remain valid between map and unmap calls. - * HERE: If we are not assuming AP v R4 same-endianess then this - * should be explicitly leu32 or u8[4] (or something equivalent). - */ - u32 *(*get_mbox_ptr)(struct scsc_mif_abs *interface, u32 mbox_index); -/** - * Incoming MIF Interrupt Hardware Controls - */ - /** Get the incoming interrupt source mask */ - u32 (*irq_bit_mask_status_get)(struct scsc_mif_abs *interface); - - /** Get the incoming interrupt pending (waiting *AND* not masked) mask */ - u32 (*irq_get)(struct scsc_mif_abs *interface); - - void (*irq_bit_clear)(struct scsc_mif_abs *interface, int bit_num); - void (*irq_bit_mask)(struct scsc_mif_abs *interface, int bit_num); - void (*irq_bit_unmask)(struct scsc_mif_abs *interface, int bit_num); - -/** - * Outgoing MIF Interrupt Hardware Controls - */ - void (*irq_bit_set)(struct scsc_mif_abs *interface, int bit_num, enum scsc_mif_abs_target target); - -/** - * Register handler for the interrupt from the - * MIF Interrupt Hardware. - * - * This is used by the MIF Interrupt Manager to - * register a handler that demultiplexes the - * individual interrupt sources (MIF Interrupt Bits) - * to source-specific handlers. - */ - void (*irq_reg_handler)(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev); - void (*irq_unreg_handler)(struct scsc_mif_abs *interface); - - /* Clear HW interrupt line */ - void (*irq_clear)(void); - void (*irq_reg_reset_request_handler)(struct scsc_mif_abs *interface, void (*handler)(int irq, void *data), void *dev); - void (*irq_unreg_reset_request_handler)(struct scsc_mif_abs *interface); - -/** - * Install suspend/resume handlers for the MIF abstraction driver - */ - void (*suspend_reg_handler)(struct scsc_mif_abs *abs, - int (*suspend)(struct scsc_mif_abs *abs, void *data), - void (*resume)(struct scsc_mif_abs *abs, void *data), - void *data); - void (*suspend_unreg_handler)(struct scsc_mif_abs *abs); - -/** - * Return kernel-space pointer to MIF ram. - * The pointer is guaranteed to remain valid between map and unmap calls. - */ - void *(*get_mifram_ptr)(struct scsc_mif_abs *interface, scsc_mifram_ref ref); -/* Maps kernel-space pointer to MIF RAM to portable reference */ - int (*get_mifram_ref)(struct scsc_mif_abs *interface, void *ptr, scsc_mifram_ref *ref); - -/* Return physical page frame number corresponding to the physical addres to which - * the virtual address is mapped . Needed in mmap file operations*/ - uintptr_t (*get_mifram_pfn)(struct scsc_mif_abs *interface); - -/** - * Return physical address from MIF ram address. - */ - void *(*get_mifram_phy_ptr)(struct scsc_mif_abs *interface, scsc_mifram_ref ref); -/** Return a kernel device associated 1:1 with the Maxwell instance. - * This is published only for the purpose of associating service drivers with a Maxwell instance - * for logging purposes. Clients should not make any assumptions about the device type. - * In some configurations this may be the associated host-interface device (AXI/PCIe), - * but this may change in future. - */ - struct device *(*get_mif_device)(struct scsc_mif_abs *interface); - - - void (*mif_dump_registers)(struct scsc_mif_abs *interface); - void (*mif_cleanup)(struct scsc_mif_abs *interface); - void (*mif_restart)(struct scsc_mif_abs *interface); - -#ifdef CONFIG_SCSC_SMAPPER -/* SMAPPER */ - int (*mif_smapper_get_mapping)(struct scsc_mif_abs *interface, u8 *phy_map, u16 *align); - int (*mif_smapper_get_bank_info)(struct scsc_mif_abs *interface, u8 bank, struct scsc_mif_smapper_info *bank_info); - int (*mif_smapper_write_sram)(struct scsc_mif_abs *interface, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr); - void (*mif_smapper_configure)(struct scsc_mif_abs *interface, u32 granularity); - u32 (*mif_smapper_get_bank_base_address)(struct scsc_mif_abs *interface, u8 bank); -#endif -#ifdef CONFIG_SCSC_QOS - int (*mif_pm_qos_add_request)(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config); - int (*mif_pm_qos_update_request)(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req, enum scsc_qos_config config); - int (*mif_pm_qos_remove_request)(struct scsc_mif_abs *interface, struct scsc_mifqos_request *qos_req); -#endif - int (*mif_read_register)(struct scsc_mif_abs *interface, u64 id, u32 *val); -}; - -struct device; - -struct scsc_mif_abs_driver { - char *name; - void (*probe)(struct scsc_mif_abs_driver *abs_driver, struct scsc_mif_abs *abs); - void (*remove)(struct scsc_mif_abs *abs); -}; - -extern void scsc_mif_abs_register(struct scsc_mif_abs_driver *driver); -extern void scsc_mif_abs_unregister(struct scsc_mif_abs_driver *driver); - -/* mmap-debug driver */ -struct scsc_mif_mmap_driver { - char *name; - void (*probe)(struct scsc_mif_mmap_driver *mmap_driver, struct scsc_mif_abs *abs); - void (*remove)(struct scsc_mif_abs *abs); -}; - -extern void scsc_mif_mmap_register(struct scsc_mif_mmap_driver *mmap_driver); -extern void scsc_mif_mmap_unregister(struct scsc_mif_mmap_driver *mmap_driver); -#endif diff --git a/drivers/misc/samsung/scsc/scsc_mx_impl.c b/drivers/misc/samsung/scsc/scsc_mx_impl.c deleted file mode 100644 index cbc3dd88a7ae..000000000000 --- a/drivers/misc/samsung/scsc/scsc_mx_impl.c +++ /dev/null @@ -1,227 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include "scsc_mx_impl.h" -#include "mifintrbit.h" -#include "miframman.h" -#include "mifmboxman.h" -#ifdef CONFIG_SCSC_SMAPPER -#include "mifsmapper.h" -#endif -#ifdef CONFIG_SCSC_QOS -#include "mifqos.h" -#endif -#include "mifproc.h" -#include "mxman.h" -#include "mxproc.h" -#include "mxsyserr.h" -#include "srvman.h" -#include "mxmgmt_transport.h" -#include "gdb_transport.h" -#include "mxlog.h" -#include "mxlogger.h" -#include "panicmon.h" -#include "mxlog_transport.h" -#include "suspendmon.h" - -#include "scsc/api/bt_audio.h" -#include "mxfwconfig.h" -#ifdef CONFIG_SCSC_WLBTD -#include "scsc_wlbtd.h" -#endif - -struct scsc_mx { - struct scsc_mif_abs *mif_abs; - struct mifintrbit intr; - struct miframman ram; - struct miframman ram2; - struct mifmboxman mbox; - struct mifabox mifabox; -#ifdef CONFIG_SCSC_SMAPPER - struct mifsmapper smapper; -#endif -#ifdef CONFIG_SCSC_QOS - struct mifqos qos; -#endif - struct mifproc proc; - struct mxman mxman; - struct srvman srvman; - struct mxmgmt_transport mxmgmt_transport; - struct gdb_transport gdb_transport_r4; - struct gdb_transport gdb_transport_m4; -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT - struct gdb_transport gdb_transport_m4_1; -#endif - int users; - struct mxlog mxlog; - struct mxlogger mxlogger; - struct panicmon panicmon; - struct mxlog_transport mxlog_transport; - struct suspendmon suspendmon; - struct mxfwconfig mxfwconfig; -}; - - -struct scsc_mx *scsc_mx_create(struct scsc_mif_abs *mif) -{ - struct scsc_mx *mx; - - mx = kzalloc(sizeof(*mx), GFP_KERNEL); - if (!mx) - return NULL; - - mx->mif_abs = mif; - - mifintrbit_init(&mx->intr, mif); - - mifmboxman_init(&mx->mbox); - suspendmon_init(&mx->suspendmon, mx); - mxman_init(&mx->mxman, mx); - srvman_init(&mx->srvman, mx); - mifproc_create_proc_dir(mx->mif_abs); -#ifdef CONFIG_SCSC_WLBTD - scsc_wlbtd_init(); -#endif - mx_syserr_init(); - SCSC_TAG_DEBUG(MXMAN, "Hurray Maxwell is here with %p\n", mx); - return mx; -} - -void scsc_mx_destroy(struct scsc_mx *mx) -{ - SCSC_TAG_DEBUG(MXMAN, "\n"); - BUG_ON(mx == NULL); - mifintrbit_deinit(&mx->intr); - mifmboxman_deinit(scsc_mx_get_mboxman(mx)); -#ifdef CONFIG_SCSC_SMAPPER - mifsmapper_deinit(scsc_mx_get_smapper(mx)); -#endif - suspendmon_deinit(scsc_mx_get_suspendmon(mx)); - mifproc_remove_proc_dir(); - srvman_deinit(&mx->srvman); - mxman_deinit(&mx->mxman); -#ifdef CONFIG_SCSC_WLBTD - scsc_wlbtd_deinit(); -#endif - kfree(mx); - SCSC_TAG_DEBUG(MXMAN, "OK\n"); -} - -struct scsc_mif_abs *scsc_mx_get_mif_abs(struct scsc_mx *mx) -{ - return mx->mif_abs; -} - -struct mifintrbit *scsc_mx_get_intrbit(struct scsc_mx *mx) -{ - return &mx->intr; -} - -struct miframman *scsc_mx_get_ramman(struct scsc_mx *mx) -{ - return &mx->ram; -} - -struct miframman *scsc_mx_get_ramman2(struct scsc_mx *mx) -{ - return &mx->ram2; -} - -struct mifabox *scsc_mx_get_aboxram(struct scsc_mx *mx) -{ - return &mx->mifabox; -} - -struct mifmboxman *scsc_mx_get_mboxman(struct scsc_mx *mx) -{ - return &mx->mbox; -} - -#ifdef CONFIG_SCSC_SMAPPER -struct mifsmapper *scsc_mx_get_smapper(struct scsc_mx *mx) -{ - return &mx->smapper; -} -#endif - -#ifdef CONFIG_SCSC_QOS -struct mifqos *scsc_mx_get_qos(struct scsc_mx *mx) -{ - return &mx->qos; -} -#endif - -struct device *scsc_mx_get_device(struct scsc_mx *mx) -{ - return mx->mif_abs->get_mif_device(mx->mif_abs); -} -EXPORT_SYMBOL_GPL(scsc_mx_get_device); /* TODO: export a top-level API for this */ - -struct mxman *scsc_mx_get_mxman(struct scsc_mx *mx) -{ - return &mx->mxman; -} - -struct srvman *scsc_mx_get_srvman(struct scsc_mx *mx) -{ - return &mx->srvman; -} - -struct mxmgmt_transport *scsc_mx_get_mxmgmt_transport(struct scsc_mx *mx) -{ - return &mx->mxmgmt_transport; -} - -struct gdb_transport *scsc_mx_get_gdb_transport_r4(struct scsc_mx *mx) -{ - return &mx->gdb_transport_r4; -} - -struct gdb_transport *scsc_mx_get_gdb_transport_m4(struct scsc_mx *mx) -{ - return &mx->gdb_transport_m4; -} - -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT -struct gdb_transport *scsc_mx_get_gdb_transport_m4_1(struct scsc_mx *mx) -{ - return &mx->gdb_transport_m4_1; -} -#endif - -struct mxlog *scsc_mx_get_mxlog(struct scsc_mx *mx) -{ - return &mx->mxlog; -} - -struct panicmon *scsc_mx_get_panicmon(struct scsc_mx *mx) -{ - return &mx->panicmon; -} - -struct mxlog_transport *scsc_mx_get_mxlog_transport(struct scsc_mx *mx) -{ - return &mx->mxlog_transport; -} - -struct mxlogger *scsc_mx_get_mxlogger(struct scsc_mx *mx) -{ - return &mx->mxlogger; -} - -struct suspendmon *scsc_mx_get_suspendmon(struct scsc_mx *mx) -{ - return &mx->suspendmon; -} - -struct mxfwconfig *scsc_mx_get_mxfwconfig(struct scsc_mx *mx) -{ - return &mx->mxfwconfig; -} - diff --git a/drivers/misc/samsung/scsc/scsc_mx_impl.h b/drivers/misc/samsung/scsc/scsc_mx_impl.h deleted file mode 100644 index d4df3466c36f..000000000000 --- a/drivers/misc/samsung/scsc/scsc_mx_impl.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef _CORE_H_ -#define _CORE_H_ - -#include -#include "scsc_mif_abs.h" - -struct device; -struct scsc_mx; -struct mifintrbit; -struct miframman; -struct mifmboxman; -struct mxman; -struct srvman; -struct mxmgmt_transport; -struct mxproc; -struct mxfwconfig; - -struct scsc_mx *scsc_mx_create(struct scsc_mif_abs *mif); -void scsc_mx_destroy(struct scsc_mx *mx); -struct scsc_mif_abs *scsc_mx_get_mif_abs(struct scsc_mx *mx); -struct mifintrbit *scsc_mx_get_intrbit(struct scsc_mx *mx); -struct mifmuxman *scsc_mx_get_muxman(struct scsc_mx *mx); -struct miframman *scsc_mx_get_ramman(struct scsc_mx *mx); -struct miframman *scsc_mx_get_ramman2(struct scsc_mx *mx); -struct mifabox *scsc_mx_get_aboxram(struct scsc_mx *mx); -struct mifmboxman *scsc_mx_get_mboxman(struct scsc_mx *mx); -#ifdef CONFIG_SCSC_SMAPPER -struct mifsmapper *scsc_mx_get_smapper(struct scsc_mx *mx); -#endif -#ifdef CONFIG_SCSC_QOS -struct mifqos *scsc_mx_get_qos(struct scsc_mx *mx); -#endif -struct device *scsc_mx_get_device(struct scsc_mx *mx); -struct mxman *scsc_mx_get_mxman(struct scsc_mx *mx); -struct srvman *scsc_mx_get_srvman(struct scsc_mx *mx); -struct mxproc *scsc_mx_get_mxproc(struct scsc_mx *mx); -struct mxmgmt_transport *scsc_mx_get_mxmgmt_transport(struct scsc_mx *mx); -struct gdb_transport *scsc_mx_get_gdb_transport_r4(struct scsc_mx *mx); -struct gdb_transport *scsc_mx_get_gdb_transport_m4(struct scsc_mx *mx); -#ifdef CONFIG_SCSC_MX450_GDB_SUPPORT -struct gdb_transport *scsc_mx_get_gdb_transport_m4_1(struct scsc_mx *mx); -#endif -struct mxlog *scsc_mx_get_mxlog(struct scsc_mx *mx); -struct mxlog_transport *scsc_mx_get_mxlog_transport(struct scsc_mx *mx); -struct mxlogger *scsc_mx_get_mxlogger(struct scsc_mx *mx); -struct panicmon *scsc_mx_get_panicmon(struct scsc_mx *mx); -struct suspendmon *scsc_mx_get_suspendmon(struct scsc_mx *mx); -struct mxfwconfig *scsc_mx_get_mxfwconfig(struct scsc_mx *mx); - -int mx140_file_download_fw(struct scsc_mx *mx, void *dest, size_t dest_size, u32 *fw_image_size); -int mx140_request_file(struct scsc_mx *mx, char *path, const struct firmware **firmp); -int mx140_release_file(struct scsc_mx *mx, const struct firmware *firmp); -int mx140_basedir_file(struct scsc_mx *mx); -int mx140_exe_path(struct scsc_mx *mx, char *path, size_t len, const char *bin); -int mx140_file_select_fw(struct scsc_mx *mx, u32 suffix); -bool mx140_file_supported_hw(struct scsc_mx *mx, u32 hw_ver); -#endif diff --git a/drivers/misc/samsung/scsc/scsc_mx_module.c b/drivers/misc/samsung/scsc/scsc_mx_module.c deleted file mode 100755 index 0b4c01b24e78..000000000000 --- a/drivers/misc/samsung/scsc/scsc_mx_module.c +++ /dev/null @@ -1,200 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include "scsc_mif_abs.h" -#include "scsc_mx_impl.h" -#ifdef CONFIG_SCSC_WLBTD -#include "scsc_wlbtd.h" -#endif - -#define SCSC_MX_CORE_MODDESC "mx140 Core Driver" - -struct clients_node { - struct list_head list; - struct scsc_mx_module_client *module_client; -}; - -struct mx_node { - struct list_head list; - struct scsc_mx *mx; -}; - -static struct mx_module { - struct list_head clients_list; - struct list_head mx_list; -} mx_module = { - .clients_list = LIST_HEAD_INIT(mx_module.clients_list), - .mx_list = LIST_HEAD_INIT(mx_module.mx_list) -}; - -static void scsc_mx_module_probe_registered_clients(struct scsc_mx *new_mx) -{ - bool client_registered = false; - struct clients_node *client_node, *client_next; - - /* Traverse Linked List for each mif_driver node */ - list_for_each_entry_safe(client_node, client_next, &mx_module.clients_list, list) { - client_node->module_client->probe(client_node->module_client, new_mx, SCSC_MODULE_CLIENT_REASON_HW_PROBE); - client_registered = true; - } - if (client_registered == false) - SCSC_TAG_INFO(MXMAN, "No clients registered\n"); -} - -static void scsc_mx_module_probe(struct scsc_mif_abs_driver *abs_driver, struct scsc_mif_abs *mif_abs) -{ - struct scsc_mx *new_mx; - struct mx_node *mx_node; - - /* Avoid unused parm error */ - (void)abs_driver; - - mx_node = kzalloc(sizeof(*mx_node), GFP_KERNEL); - if (!mx_node) - return; - /* Create new mx instance */ - new_mx = scsc_mx_create(mif_abs); - if (!new_mx) { - kfree(mx_node); - SCSC_TAG_ERR(MXMAN, "Error allocating new_mx\n"); - return; - } - /* Add instance in mx_node linked list */ - mx_node->mx = new_mx; - - list_add_tail(&mx_node->list, &mx_module.mx_list); - - scsc_mx_module_probe_registered_clients(new_mx); -} - -static void scsc_mx_module_remove(struct scsc_mif_abs *abs) -{ - bool match = false; - struct mx_node *mx_node, *next; - - /* Traverse Linked List for each mx node */ - list_for_each_entry_safe(mx_node, next, &mx_module.mx_list, list) { - /* If there is a match, call destroy */ - if (scsc_mx_get_mif_abs(mx_node->mx) == abs) { - match = true; - scsc_mx_destroy(mx_node->mx); - list_del(&mx_node->list); - kfree(mx_node); - } - } - if (match == false) - SCSC_TAG_ERR(MXMAN, "FATAL, no match for given scsc_mif_abs\n"); -} - -static struct scsc_mif_abs_driver mx_module_mif_if = { - .name = "mx140 driver", - .probe = scsc_mx_module_probe, - .remove = scsc_mx_module_remove, -}; - -static int __init scsc_mx_module_init(void) -{ - SCSC_TAG_INFO(MXMAN, SCSC_MX_CORE_MODDESC " scsc_release %d.%d.%d.%d\n", - SCSC_RELEASE_PRODUCT, - SCSC_RELEASE_ITERATION, - SCSC_RELEASE_CANDIDATE, - SCSC_RELEASE_POINT); - - scsc_mif_abs_register(&mx_module_mif_if); - return 0; -} - -static void __exit scsc_mx_module_exit(void) -{ - struct mx_node *mx_node, *next_mx; - - /* Traverse Linked List for each mx node */ - list_for_each_entry_safe(mx_node, next_mx, &mx_module.mx_list, list) { - scsc_mx_destroy(mx_node->mx); - list_del(&mx_node->list); - kfree(mx_node); - } - - scsc_mif_abs_unregister(&mx_module_mif_if); - - SCSC_TAG_INFO(MXMAN, SCSC_MX_CORE_MODDESC " unloaded\n"); -} - -/** - * Reset all registered service drivers by first calling the remove callback and - * then the probe callback. This function is used during recovery operations, - * where the chip has been reset as part of the recovery and the service drivers - * has to do the same. - */ -int scsc_mx_module_reset(void) -{ - struct clients_node *clients_node; - struct mx_node *mx_node, *next_mx; - - /* Traverse Linked List and call registered removed callbacks */ - list_for_each_entry_safe(mx_node, next_mx, &mx_module.mx_list, list) - list_for_each_entry(clients_node, &mx_module.clients_list, list) - clients_node->module_client->remove(clients_node->module_client, mx_node->mx, SCSC_MODULE_CLIENT_REASON_RECOVERY); - - /* Traverse Linked List and call registered probed callbacks */ - list_for_each_entry_safe(mx_node, next_mx, &mx_module.mx_list, list) - list_for_each_entry(clients_node, &mx_module.clients_list, list) - clients_node->module_client->probe(clients_node->module_client, mx_node->mx, SCSC_MODULE_CLIENT_REASON_RECOVERY); - - return 0; -} -EXPORT_SYMBOL(scsc_mx_module_reset); - -int scsc_mx_module_register_client_module(struct scsc_mx_module_client *module_client) -{ - struct clients_node *module_client_node; - struct mx_node *mx_node; - - /* Add node in modules linked list */ - module_client_node = kzalloc(sizeof(*module_client_node), GFP_KERNEL); - if (!module_client_node) - return -ENOMEM; - - module_client_node->module_client = module_client; - list_add_tail(&module_client_node->list, &mx_module.clients_list); - - /* Traverse Linked List for each mx node */ - list_for_each_entry(mx_node, &mx_module.mx_list, list) { - module_client->probe(module_client, mx_node->mx, SCSC_MODULE_CLIENT_REASON_HW_PROBE); - } - return 0; -} -EXPORT_SYMBOL(scsc_mx_module_register_client_module); - -void scsc_mx_module_unregister_client_module(struct scsc_mx_module_client *module_client) -{ - struct clients_node *client_node, *client_next; - struct mx_node *mx_node, *next_mx; - - /* Traverse Linked List for each client_list */ - list_for_each_entry_safe(client_node, client_next, &mx_module.clients_list, list) { - if (client_node->module_client == module_client) { - list_for_each_entry_safe(mx_node, next_mx, &mx_module.mx_list, list) { - module_client->remove(module_client, mx_node->mx, SCSC_MODULE_CLIENT_REASON_HW_REMOVE); - } - list_del(&client_node->list); - kfree(client_node); - } - } -} -EXPORT_SYMBOL(scsc_mx_module_unregister_client_module); - -module_init(scsc_mx_module_init); -module_exit(scsc_mx_module_exit); - -MODULE_DESCRIPTION(SCSC_MX_CORE_MODDESC); -MODULE_AUTHOR("SCSC"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/samsung/scsc/scsc_service.c b/drivers/misc/samsung/scsc/scsc_service.c deleted file mode 100755 index 291c867831a6..000000000000 --- a/drivers/misc/samsung/scsc/scsc_service.c +++ /dev/null @@ -1,1233 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#ifdef CONFIG_ANDROID -#include -#endif -#include -#include - -#include "mxman.h" -#include "scsc_mx_impl.h" -#include "mifintrbit.h" -#include "miframman.h" -#include "mifmboxman.h" -#ifdef CONFIG_SCSC_SMAPPER -#include "mifsmapper.h" -#endif -#ifdef CONFIG_SCSC_QOS -#include "mifqos.h" -#endif -#include "mxlogger.h" -#include "srvman.h" -#include "servman_messages.h" -#include "mxmgmt_transport.h" - -static ulong sm_completion_timeout_ms = 1000; -module_param(sm_completion_timeout_ms, ulong, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(sm_completion_timeout_ms, "Timeout Service Manager start/stop (ms) - default 1000. 0 = infinite"); - -#define SCSC_MIFRAM_INVALID_REF -1 -#define SCSC_MX_SERVICE_RECOVERY_TIMEOUT 20000 /* 20 seconds */ - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) -#define reinit_completion(completion) INIT_COMPLETION(*(completion)) -#endif - -struct scsc_service { - struct list_head list; - struct scsc_mx *mx; - enum scsc_service_id id; - struct scsc_service_client *client; - struct completion sm_msg_start_completion; - struct completion sm_msg_stop_completion; -}; - -/* true if a service is part of a sub-system that is reported by system error */ -#define SERVICE_IN_SUBSYSTEM(service, subsys) \ - (((subsys == SYSERR_SUBSYS_WLAN) && (service == SCSC_SERVICE_ID_WLAN)) || \ - ((subsys == SYSERR_SUBSYS_BT) && ((service == SCSC_SERVICE_ID_BT) || (service == SCSC_SERVICE_ID_ANT)))) - -void srvman_init(struct srvman *srvman, struct scsc_mx *mx) -{ - SCSC_TAG_INFO(MXMAN, "\n"); - srvman->mx = mx; - INIT_LIST_HEAD(&srvman->service_list); - mutex_init(&srvman->service_list_mutex); - mutex_init(&srvman->api_access_mutex); - -#ifdef CONFIG_ANDROID - wake_lock_init(&srvman->sm_wake_lock, WAKE_LOCK_SUSPEND, "srvman_wakelock"); -#endif -} - -void srvman_deinit(struct srvman *srvman) -{ - struct scsc_service *service, *next; - - SCSC_TAG_INFO(MXMAN, "\n"); - list_for_each_entry_safe(service, next, &srvman->service_list, list) { - list_del(&service->list); - kfree(service); - } - mutex_destroy(&srvman->api_access_mutex); - mutex_destroy(&srvman->service_list_mutex); - -#ifdef CONFIG_ANDROID - wake_lock_destroy(&srvman->sm_wake_lock); -#endif -} - -void srvman_set_error(struct srvman *srvman) -{ - struct scsc_service *service; - - SCSC_TAG_INFO(MXMAN, "\n"); - srvman->error = true; - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - complete(&service->sm_msg_start_completion); - complete(&service->sm_msg_stop_completion); - } - mutex_unlock(&srvman->service_list_mutex); -} - -void srvman_clear_error(struct srvman *srvman) -{ - SCSC_TAG_INFO(MXMAN, "\n"); - srvman->error = false; -} - -static int wait_for_sm_msg_start_cfm(struct scsc_service *service) -{ - int r; - - if (0 == sm_completion_timeout_ms) { - /* Zero implies infinite wait, for development use only. - * r = -ERESTARTSYS if interrupted (e.g. Ctrl-C), 0 if completed - */ - r = wait_for_completion_interruptible(&service->sm_msg_start_completion); - if (r == -ERESTARTSYS) { - /* Paranoid sink of any pending event skipped by the interrupted wait */ - r = wait_for_completion_timeout(&service->sm_msg_start_completion, HZ / 2); - if (r == 0) { - SCSC_TAG_ERR(MXMAN, "timed out\n"); - return -ETIMEDOUT; - } - } - return r; - } - r = wait_for_completion_timeout(&service->sm_msg_start_completion, msecs_to_jiffies(sm_completion_timeout_ms)); - if (r == 0) { - SCSC_TAG_ERR(MXMAN, "timeout\n"); - return -ETIMEDOUT; - } - return 0; -} - -static int wait_for_sm_msg_stop_cfm(struct scsc_service *service) -{ - int r; - - if (0 == sm_completion_timeout_ms) { - /* Zero implies infinite wait, for development use only. - * r = -ERESTARTSYS if interrupted (e.g. Ctrl-C), 0 if completed - */ - r = wait_for_completion_interruptible(&service->sm_msg_stop_completion); - if (r == -ERESTARTSYS) { - /* Paranoid sink of any pending event skipped by the interrupted wait */ - r = wait_for_completion_timeout(&service->sm_msg_stop_completion, HZ / 2); - if (r == 0) { - SCSC_TAG_ERR(MXMAN, "timed out\n"); - return -ETIMEDOUT; - } - } - return r; - } - r = wait_for_completion_timeout(&service->sm_msg_stop_completion, msecs_to_jiffies(sm_completion_timeout_ms)); - if (r == 0) { - SCSC_TAG_ERR(MXMAN, "timeout\n"); - return -ETIMEDOUT; - } - return 0; -} - -static int send_sm_msg_start_blocking(struct scsc_service *service, scsc_mifram_ref ref) -{ - struct scsc_mx *mx = service->mx; - struct mxmgmt_transport *mxmgmt_transport = scsc_mx_get_mxmgmt_transport(mx); - int r; - struct sm_msg_packet message = { .service_id = service->id, - .msg = SM_MSG_START_REQ, - .optional_data = ref }; - - reinit_completion(&service->sm_msg_start_completion); - - /* Send to FW in MM stream */ - mxmgmt_transport_send(mxmgmt_transport, MMTRANS_CHAN_ID_SERVICE_MANAGEMENT, &message, sizeof(message)); - r = wait_for_sm_msg_start_cfm(service); - if (r) { - SCSC_TAG_ERR(MXMAN, "wait_for_sm_msg_start_cfm() failed: r=%d\n", r); - - /* Report the error in order to get a moredump. Avoid auto-recovering this type of failure */ - if (mxman_recovery_disabled()) - scsc_mx_service_service_failed(service, "SM_MSG_START_CFM timeout"); - } - return r; -} - -static int send_sm_msg_stop_blocking(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - struct mxman *mxman = scsc_mx_get_mxman(mx); - struct mxmgmt_transport *mxmgmt_transport = scsc_mx_get_mxmgmt_transport(mx); - int r; - struct sm_msg_packet message = { .service_id = service->id, - .msg = SM_MSG_STOP_REQ, - .optional_data = 0 }; - - if (mxman->mxman_state == MXMAN_STATE_FAILED) - return 0; - - reinit_completion(&service->sm_msg_stop_completion); - - /* Send to FW in MM stream */ - mxmgmt_transport_send(mxmgmt_transport, MMTRANS_CHAN_ID_SERVICE_MANAGEMENT, &message, sizeof(message)); - r = wait_for_sm_msg_stop_cfm(service); - if (r) - SCSC_TAG_ERR(MXMAN, "wait_for_sm_msg_stop_cfm() for service=%p service->id=%d failed: r=%d\n", service, service->id, r); - return r; -} - -/* - * Receive handler for messages from the FW along the maxwell management transport - */ -static void srv_message_handler(const void *message, void *data) -{ - struct srvman *srvman = (struct srvman *)data; - struct scsc_service *service; - const struct sm_msg_packet *msg = message; - bool found = false; - - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if (service->id == msg->service_id) { - found = true; - break; - } - } - if (!found) { - SCSC_TAG_ERR(MXMAN, "No service for msg->service_id=%d", msg->service_id); - mutex_unlock(&srvman->service_list_mutex); - return; - } - /* Forward the message to the applicable service to deal with */ - switch (msg->msg) { - case SM_MSG_START_CFM: - SCSC_TAG_INFO(MXMAN, "Received SM_MSG_START_CFM message service=%p with service_id=%d from the firmware\n", - service, msg->service_id); - complete(&service->sm_msg_start_completion); - break; - case SM_MSG_STOP_CFM: - SCSC_TAG_INFO(MXMAN, "Received SM_MSG_STOP_CFM message for service=%p with service_id=%d from the firmware\n", - service, msg->service_id); - complete(&service->sm_msg_stop_completion); - break; - default: - /* HERE: Unknown message, raise fault */ - SCSC_TAG_WARNING(MXMAN, "Received unknown message for service=%p with service_id=%d from the firmware: msg->msg=%d\n", - service, msg->msg, msg->service_id); - break; - } - mutex_unlock(&srvman->service_list_mutex); -} - -int scsc_mx_service_start(struct scsc_service *service, scsc_mifram_ref ref) -{ - struct scsc_mx *mx = service->mx; - struct srvman *srvman = scsc_mx_get_srvman(mx); - struct mxman *mxman = scsc_mx_get_mxman(service->mx); - int r; - struct timeval tval = {}; - - SCSC_TAG_INFO(MXMAN, "%d\n", service->id); -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_run) - return 0; -#endif - mutex_lock(&srvman->api_access_mutex); -#ifdef CONFIG_ANDROID - wake_lock(&srvman->sm_wake_lock); -#endif - if (srvman->error) { - tval = ns_to_timeval(mxman->last_panic_time); - SCSC_TAG_ERR(MXMAN, "error: refused due to previous f/w failure scsc_panic_code=0x%x happened at [%6lu.%06ld]\n", - mxman->scsc_panic_code, tval.tv_sec, tval.tv_usec); - - /* Print the last panic record to help track ancient failures */ - mxman_show_last_panic(mxman); - -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - return -EILSEQ; - } - - r = send_sm_msg_start_blocking(service, ref); - if (r) { - SCSC_TAG_ERR(MXMAN, "send_sm_msg_start_blocking() failed: r=%d\n", r); -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - return r; - } - -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - return 0; -} -EXPORT_SYMBOL(scsc_mx_service_start); - -int scsc_mx_list_services(struct mxman *mxman_p, char *buf, const size_t bufsz) -{ - struct scsc_service *service, *next; - int pos = 0; - struct srvman *srvman_p = scsc_mx_get_srvman(mxman_p->mx); - - list_for_each_entry_safe(service, next, &srvman_p->service_list, list) { - switch (service->id) { - case SCSC_SERVICE_ID_NULL: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "null"); - break; - case SCSC_SERVICE_ID_WLAN: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "wlan"); - break; - case SCSC_SERVICE_ID_BT: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "bt"); - break; - case SCSC_SERVICE_ID_ANT: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "ant"); - break; - case SCSC_SERVICE_ID_R4DBG: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "r4dbg"); - break; - case SCSC_SERVICE_ID_ECHO: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "echo"); - break; - case SCSC_SERVICE_ID_DBG_SAMPLER: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "dbg sampler"); - break; - case SCSC_SERVICE_ID_CLK20MHZ: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "clk20mhz"); - break; - case SCSC_SERVICE_ID_FM: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "fm"); - break; - case SCSC_SERVICE_ID_INVALID: - pos += scnprintf(buf + pos, bufsz - pos, "%s\n", "invalid"); - break; - } - } - return pos; -} -EXPORT_SYMBOL(scsc_mx_list_services); - -int scsc_mx_service_stop(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - struct srvman *srvman = scsc_mx_get_srvman(mx); - struct mxman *mxman = scsc_mx_get_mxman(service->mx); - int r; - struct timeval tval = {}; - - SCSC_TAG_INFO(MXMAN, "%d\n", service->id); -#ifdef CONFIG_SCSC_CHV_SUPPORT - if (chv_run) - return 0; -#endif - mutex_lock(&srvman->api_access_mutex); -#ifdef CONFIG_ANDROID - wake_lock(&srvman->sm_wake_lock); -#endif - if (srvman->error) { - tval = ns_to_timeval(mxman->last_panic_time); - SCSC_TAG_ERR(MXMAN, "error: refused due to previous f/w failure scsc_panic_code=0x%x happened at [%6lu.%06ld]\n", - mxman->scsc_panic_code, tval.tv_sec, tval.tv_usec); - - /* Print the last panic record to help track ancient failures */ - mxman_show_last_panic(mxman); - -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - - /* Return a special status to allow caller recovery logic to know - * that there will never be a recovery - */ - if (mxman_recovery_disabled()) { - SCSC_TAG_ERR(MXMAN, "recovery disabled, return -EPERM (%d)\n", -EPERM); - return -EPERM; /* failed due to prior failure, recovery disabled */ - } else { - return -EILSEQ; /* operation rejected due to prior failure */ - } - } - - r = send_sm_msg_stop_blocking(service); - if (r) { - SCSC_TAG_ERR(MXMAN, "send_sm_msg_stop_blocking() failed: r=%d\n", r); -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - return -EIO; /* operation failed */ - } - -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - return 0; -} -EXPORT_SYMBOL(scsc_mx_service_stop); - - -/* Returns 0 if Suspend succeeded, otherwise return error */ -int srvman_suspend_services(struct srvman *srvman) -{ - int ret = 0; - struct scsc_service *service; - - SCSC_TAG_INFO(MXMAN, "\n"); - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if (service->client->suspend) { - ret = service->client->suspend(service->client); - /* If any service returns error message and call resume callbacks */ - if (ret) { - list_for_each_entry(service, &srvman->service_list, list) { - if (service->client->resume) - service->client->resume(service->client); - } - SCSC_TAG_INFO(MXMAN, "Service client suspend failure ret: %d\n", ret); - mutex_unlock(&srvman->service_list_mutex); - return ret; - } - } - } - - mutex_unlock(&srvman->service_list_mutex); - SCSC_TAG_INFO(MXMAN, "OK\n"); - return 0; -} - -/* Returns always 0. Extend API and return value if required */ -int srvman_resume_services(struct srvman *srvman) -{ - struct scsc_service *service; - - SCSC_TAG_INFO(MXMAN, "\n"); - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if (service->client->resume) - service->client->resume(service->client); - } - - mutex_unlock(&srvman->service_list_mutex); - SCSC_TAG_INFO(MXMAN, "OK\n"); - - return 0; -} - -void srvman_freeze_services(struct srvman *srvman, struct mx_syserr_decode *syserr) -{ - struct scsc_service *service; - struct mxman *mxman = scsc_mx_get_mxman(srvman->mx); - - SCSC_TAG_INFO(MXMAN, "\n"); - mxman->notify = false; - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if (service->client->stop_on_failure) { - service->client->stop_on_failure(service->client); - mxman->notify = true; - } else if ((service->client->stop_on_failure_v2) && - (service->client->stop_on_failure_v2(service->client, syserr))) - mxman->notify = true; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) - reinit_completion(&mxman->recovery_completion); -#else - INIT_COMPLETION(mxman->recovery_completion); -#endif - mutex_unlock(&srvman->service_list_mutex); - SCSC_TAG_INFO(MXMAN, "OK\n"); -} - -void srvman_freeze_sub_system(struct srvman *srvman, struct mx_syserr_decode *syserr) -{ - struct scsc_service *service; - struct mxman *mxman = scsc_mx_get_mxman(srvman->mx); - - SCSC_TAG_INFO(MXMAN, "\n"); - mxman->notify = false; - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if ((SERVICE_IN_SUBSYSTEM(service->id, syserr->subsys) && (service->client->stop_on_failure_v2))) - if (service->client->stop_on_failure_v2(service->client, syserr)) - mxman->notify = true; - } - mutex_unlock(&srvman->service_list_mutex); - SCSC_TAG_INFO(MXMAN, "OK\n"); -} - -void srvman_unfreeze_services(struct srvman *srvman, u16 scsc_panic_code) -{ - struct scsc_service *service; - struct mxman *mxman = scsc_mx_get_mxman(srvman->mx); - - SCSC_TAG_INFO(MXMAN, "\n"); - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if (service->client->failure_reset) - service->client->failure_reset(service->client, scsc_panic_code); - else if (service->client->failure_reset_v2) - service->client->failure_reset_v2(service->client, MX_SYSERR_LEVEL_7, - mxman->notify ? scsc_panic_code : MX_NULL_SYSERR); - } - mutex_unlock(&srvman->service_list_mutex); - SCSC_TAG_INFO(MXMAN, "OK\n"); -} - -void srvman_unfreeze_sub_system(struct srvman *srvman, struct mx_syserr_decode *syserr) -{ - struct scsc_service *service; - struct mxman *mxman = scsc_mx_get_mxman(srvman->mx); - - SCSC_TAG_INFO(MXMAN, "\n"); - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if ((SERVICE_IN_SUBSYSTEM(service->id, syserr->subsys) && (service->client->failure_reset_v2))) - service->client->failure_reset_v2(service->client, syserr->level, - mxman->notify ? syserr->subcode : MX_NULL_SYSERR); - } - mutex_unlock(&srvman->service_list_mutex); - SCSC_TAG_INFO(MXMAN, "OK\n"); -} - -u8 srvman_notify_sub_system(struct srvman *srvman, struct mx_syserr_decode *syserr) -{ - struct scsc_service *service; - u8 initial_level = syserr->level; - u8 final_level = syserr->level; - bool wlan_active = false; - bool bt_active = false; - bool affected_service_found = false; - - SCSC_TAG_INFO(MXMAN, "\n"); - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(service, &srvman->service_list, list) { - if (SERVICE_IN_SUBSYSTEM(service->id, SYSERR_SUBSYS_WLAN)) - wlan_active = true; - else if (SERVICE_IN_SUBSYSTEM(service->id, SYSERR_SUBSYS_BT)) - bt_active = true; - if ((SERVICE_IN_SUBSYSTEM(service->id, syserr->subsys) && (service->client->failure_notification))) { - u8 level = service->client->failure_notification(service->client, syserr); - - affected_service_found = true; - if (level > final_level) - final_level = level; - } - } - mutex_unlock(&srvman->service_list_mutex); - - if (final_level == MX_SYSERR_LEVEL_7) - SCSC_TAG_INFO(MXMAN, "System error level %d raised to full reset", initial_level); - else if ((!(wlan_active && bt_active)) && (final_level >= MX_SYSERR_LEVEL_5)) { - final_level = MX_SYSERR_LEVEL_6; /* Still a sub-system reset even though we will do a full restart */ - SCSC_TAG_INFO(MXMAN, "System error %d now level %d with 1 service active", initial_level, final_level); - } - - SCSC_TAG_INFO(MXMAN, "OK\n"); - - /* Handle race condition with affected service being closed by demoting severity to stop any recovery - * should not be possible, but best be careful anyway - */ - if ((!affected_service_found) && (final_level >= MX_SYSERR_LEVEL_5)) { - SCSC_TAG_INFO(MXMAN, "System error %d demoted to 4 as no services affected", final_level); - final_level = MX_SYSERR_LEVEL_4; - } - - return final_level; -} - - -/** Signal a failure detected by the Client. This will trigger the systemwide - * failure handling procedure: _All_ Clients will be called back via - * their stop_on_failure() handler as a side-effect. - */ -void scsc_mx_service_service_failed(struct scsc_service *service, const char *reason) -{ - struct scsc_mx *mx = service->mx; - struct srvman *srvman = scsc_mx_get_srvman(mx); - u16 host_panic_code; - - host_panic_code = (SCSC_PANIC_CODE_HOST << 15) | (service->id << SCSC_SYSERR_HOST_SERVICE_SHIFT); - - srvman_set_error(srvman); - switch (service->id) { - case SCSC_SERVICE_ID_WLAN: - SCSC_TAG_INFO(MXMAN, "WLAN: %s\n", ((reason != NULL) ? reason : "")); - break; - case SCSC_SERVICE_ID_BT: - SCSC_TAG_INFO(MXMAN, "BT: %s\n", ((reason != NULL) ? reason : "")); - break; - default: - SCSC_TAG_INFO(MXMAN, "service id %d failed\n", service->id); - break; - - } - - SCSC_TAG_INFO(MXMAN, "Reporting host hang code 0x%02x\n", host_panic_code); - - mxman_fail(scsc_mx_get_mxman(mx), host_panic_code, reason); -} -EXPORT_SYMBOL(scsc_mx_service_service_failed); - - -int scsc_mx_service_close(struct scsc_service *service) -{ - struct mxman *mxman = scsc_mx_get_mxman(service->mx); - struct scsc_mx *mx = service->mx; - struct srvman *srvman = scsc_mx_get_srvman(mx); - bool empty; - struct timeval tval = {}; - - SCSC_TAG_INFO(MXMAN, "%d\n", service->id); - - mutex_lock(&srvman->api_access_mutex); -#ifdef CONFIG_ANDROID - wake_lock(&srvman->sm_wake_lock); -#endif - - /* TODO - Race conditions here unless we protect better - * code assumes srvman->error and mxman->state can't change, but they can - */ - if (srvman->error) { - tval = ns_to_timeval(mxman->last_panic_time); - SCSC_TAG_ERR(MXMAN, "error: refused due to previous f/w failure scsc_panic_code=0x%x happened at [%6lu.%06ld]\n", - mxman->scsc_panic_code, tval.tv_sec, tval.tv_usec); - - /* Print the last panic record to help track ancient failures */ - mxman_show_last_panic(mxman); - - mutex_unlock(&srvman->api_access_mutex); -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - - /* Return a special status when recovery is disabled, to allow - * calling recovery logic to be aware that recovery is disabled, - * hence not wait for recovery events. - */ - if (mxman_recovery_disabled()) { - SCSC_TAG_ERR(MXMAN, "recovery disabled, return -EPERM (%d)\n", -EPERM); - return -EPERM; /* rejected due to prior failure, recovery disabled */ - } else { - return -EIO; - } - } - - /* remove the service from the list and deallocate the service memory */ - mutex_lock(&srvman->service_list_mutex); - list_del(&service->list); - empty = list_empty(&srvman->service_list); - mutex_unlock(&srvman->service_list_mutex); - if (empty) { - /* unregister channel handler */ - mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mx), MMTRANS_CHAN_ID_SERVICE_MANAGEMENT, - NULL, NULL); - /* Clear any system error information */ - mxman->syserr_recovery_in_progress = false; - mxman->last_syserr_recovery_time = 0; - } else if (mxman->syserr_recovery_in_progress) { - /* If we have syserr_recovery_in_progress and all the services we have asked to close are now closed, - * we can clear it now - don't wait for open as it may not come - do it now! - */ - struct scsc_service *serv; - bool all_cleared = true; - - mutex_lock(&srvman->service_list_mutex); - list_for_each_entry(serv, &srvman->service_list, list) { - if (SERVICE_IN_SUBSYSTEM(serv->id, mxman->last_syserr.subsys)) - all_cleared = false; - } - mutex_unlock(&srvman->service_list_mutex); - - if (all_cleared) - mxman->syserr_recovery_in_progress = false; - } - - kfree(service); - - mxman_close(mxman); -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - return 0; -} -EXPORT_SYMBOL(scsc_mx_service_close); - -/* Consider move to a public scsc_mx interface */ -struct scsc_service *scsc_mx_service_open(struct scsc_mx *mx, enum scsc_service_id id, struct scsc_service_client *client, int *status) -{ - int ret; - struct scsc_service *service; - struct srvman *srvman = scsc_mx_get_srvman(mx); - struct mxman *mxman = scsc_mx_get_mxman(mx); - bool empty; - struct timeval tval = {}; - - SCSC_TAG_INFO(MXMAN, "%d\n", id); - - mutex_lock(&srvman->api_access_mutex); -#ifdef CONFIG_ANDROID - wake_lock(&srvman->sm_wake_lock); -#endif - /* TODO - need to close potential race conditions - see close */ - /* Have to check for disabled here as there is a small window where error is asserted - * even if we are going to allow recovery later on - in these cases we will want to block - */ - if ((srvman->error) && (mxman_recovery_disabled())) { - tval = ns_to_timeval(mxman->last_panic_time); - SCSC_TAG_ERR(MXMAN, "error: refused due to previous f/w failure scsc_panic_code=0x%x happened at [%6lu.%06ld]\n", - mxman->scsc_panic_code, tval.tv_sec, tval.tv_usec); - /* Print the last panic record to help track ancient failures */ - mxman_show_last_panic(mxman); -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - *status = -EILSEQ; - return NULL; - } - - if (mxman->mxman_state == MXMAN_STATE_FAILED) { - int r; - - mutex_unlock(&srvman->api_access_mutex); - r = wait_for_completion_timeout(&mxman->recovery_completion, - msecs_to_jiffies(SCSC_MX_SERVICE_RECOVERY_TIMEOUT)); - if (r == 0) { - SCSC_TAG_ERR(MXMAN, "Recovery timeout\n"); -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - *status = -EIO; - return NULL; - } - - mutex_lock(&srvman->api_access_mutex); - } - - service = kmalloc(sizeof(struct scsc_service), GFP_KERNEL); - if (service) { - /* MaxwellManager Should allocate Mem and download FW */ - ret = mxman_open(mxman); - if (ret) { - kfree(service); -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - *status = ret; - return NULL; - } - /* Initialise service struct here */ - service->mx = mx; - service->id = id; - service->client = client; - init_completion(&service->sm_msg_start_completion); - init_completion(&service->sm_msg_stop_completion); - mutex_lock(&srvman->service_list_mutex); - empty = list_empty(&srvman->service_list); - mutex_unlock(&srvman->service_list_mutex); - if (empty) - mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mx), MMTRANS_CHAN_ID_SERVICE_MANAGEMENT, - &srv_message_handler, srvman); - mutex_lock(&srvman->service_list_mutex); - list_add_tail(&service->list, &srvman->service_list); - mutex_unlock(&srvman->service_list_mutex); - } else - *status = -ENOMEM; - -#ifdef CONFIG_ANDROID - wake_unlock(&srvman->sm_wake_lock); -#endif - mutex_unlock(&srvman->api_access_mutex); - - return service; -} -EXPORT_SYMBOL(scsc_mx_service_open); - -struct scsc_bt_audio_abox *scsc_mx_service_get_bt_audio_abox(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - struct mifabox *ptr; - - ptr = scsc_mx_get_aboxram(mx); - - return ptr->aboxram; -} - -struct mifabox *scsc_mx_service_get_aboxram(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - struct mifabox *ptr; - - ptr = scsc_mx_get_aboxram(mx); - - return ptr; -} - -/** - * Allocate a contiguous block of SDRAM accessible to Client Driver - * - * When allocation fails, beside returning -ENOMEM, the IN-param 'ref' - * is cleared to an INVALID value that can be safely fed to the companion - * function scsc_mx_service_mifram_free(). - */ -int scsc_mx_service_mifram_alloc_extended(struct scsc_service *service, size_t nbytes, scsc_mifram_ref *ref, u32 align, uint32_t flags) -{ - struct scsc_mx *mx = service->mx; - void *mem; - int ret; - struct miframman *ramman; - - if (flags & MIFRAMMAN_MEM_POOL_GENERIC) { - ramman = scsc_mx_get_ramman(mx); - } else if (flags & MIFRAMMAN_MEM_POOL_LOGGING) { - ramman = scsc_mx_get_ramman2(mx); - } else { - SCSC_TAG_ERR(MXMAN, "Unsupported flags value: %d", flags); - *ref = SCSC_MIFRAM_INVALID_REF; - return -ENOMEM; - } - - mem = miframman_alloc(ramman, nbytes, align, service->id); - if (!mem) { - SCSC_TAG_ERR(MXMAN, "miframman_alloc() failed\n"); - *ref = SCSC_MIFRAM_INVALID_REF; - return -ENOMEM; - } - - SCSC_TAG_DEBUG(MXMAN, "Allocated mem %p\n", mem); - - /* Transform native pointer and get mifram_ref type */ - ret = scsc_mx_service_mif_ptr_to_addr(service, mem, ref); - if (ret) { - SCSC_TAG_ERR(MXMAN, "scsc_mx_service_mif_ptr_to_addr() failed: ret=%d", ret); - miframman_free(ramman, mem); - *ref = SCSC_MIFRAM_INVALID_REF; - } else { - SCSC_TAG_DEBUG(MXMAN, "mem %p ref %d\n", mem, *ref); - } - return ret; -} -EXPORT_SYMBOL(scsc_mx_service_mifram_alloc_extended); - -int scsc_mx_service_mifram_alloc(struct scsc_service *service, size_t nbytes, scsc_mifram_ref *ref, u32 align) -{ - return scsc_mx_service_mifram_alloc_extended(service, nbytes, ref, align, MIFRAMMAN_MEM_POOL_GENERIC); -} -EXPORT_SYMBOL(scsc_mx_service_mifram_alloc); - -/** Free a contiguous block of SDRAM */ -void scsc_mx_service_mifram_free_extended(struct scsc_service *service, scsc_mifram_ref ref, uint32_t flags) -{ - struct scsc_mx *mx = service->mx; - void *mem; - struct miframman *ramman; - - if (flags & MIFRAMMAN_MEM_POOL_GENERIC) { - ramman = scsc_mx_get_ramman(mx); - } else if (flags & MIFRAMMAN_MEM_POOL_LOGGING) { - ramman = scsc_mx_get_ramman2(mx); - } else { - SCSC_TAG_ERR(MXMAN, "Unsupported flags value: %d", flags); - return; - } - - mem = scsc_mx_service_mif_addr_to_ptr(service, ref); - - SCSC_TAG_DEBUG(MXMAN, "**** Freeing %p\n", mem); - - miframman_free(ramman, mem); -} -EXPORT_SYMBOL(scsc_mx_service_mifram_free_extended); - -void scsc_mx_service_mifram_free(struct scsc_service *service, scsc_mifram_ref ref) -{ - scsc_mx_service_mifram_free_extended(service, ref, MIFRAMMAN_MEM_POOL_GENERIC); -} -EXPORT_SYMBOL(scsc_mx_service_mifram_free); - -/* MIF ALLOCATIONS */ -bool scsc_mx_service_alloc_mboxes(struct scsc_service *service, int n, int *first_mbox_index) -{ - struct scsc_mx *mx = service->mx; - - return mifmboxman_alloc_mboxes(scsc_mx_get_mboxman(mx), n, first_mbox_index); -} -EXPORT_SYMBOL(scsc_mx_service_alloc_mboxes); - -void scsc_service_free_mboxes(struct scsc_service *service, int n, int first_mbox_index) -{ - struct scsc_mx *mx = service->mx; - - return mifmboxman_free_mboxes(scsc_mx_get_mboxman(mx), first_mbox_index, n); -} -EXPORT_SYMBOL(scsc_service_free_mboxes); - -u32 *scsc_mx_service_get_mbox_ptr(struct scsc_service *service, int mbox_index) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx), mif_abs, mbox_index); -} -EXPORT_SYMBOL(scsc_mx_service_get_mbox_ptr); - -int scsc_service_mifintrbit_bit_mask_status_get(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mif_abs->irq_bit_mask_status_get(mif_abs); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_bit_mask_status_get); - -int scsc_service_mifintrbit_get(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mif_abs->irq_get(mif_abs); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_get); - -void scsc_service_mifintrbit_bit_set(struct scsc_service *service, int which_bit, enum scsc_mifintr_target dir) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mif_abs->irq_bit_set(mif_abs, which_bit, (enum scsc_mif_abs_target)dir); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_bit_set); - -void scsc_service_mifintrbit_bit_clear(struct scsc_service *service, int which_bit) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mif_abs->irq_bit_clear(mif_abs, which_bit); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_bit_clear); - -void scsc_service_mifintrbit_bit_mask(struct scsc_service *service, int which_bit) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mif_abs->irq_bit_mask(mif_abs, which_bit); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_bit_mask); - -void scsc_service_mifintrbit_bit_unmask(struct scsc_service *service, int which_bit) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mif_abs->irq_bit_unmask(mif_abs, which_bit); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_bit_unmask); - -int scsc_service_mifintrbit_alloc_fromhost(struct scsc_service *service, enum scsc_mifintr_target dir) -{ - struct scsc_mx *mx = service->mx; - - return mifintrbit_alloc_fromhost(scsc_mx_get_intrbit(mx), (enum scsc_mif_abs_target)dir); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_alloc_fromhost); - -int scsc_service_mifintrbit_free_fromhost(struct scsc_service *service, int which_bit, enum scsc_mifintr_target dir) -{ - struct scsc_mx *mx = service->mx; - - return mifintrbit_free_fromhost(scsc_mx_get_intrbit(mx), which_bit, (enum scsc_mif_abs_target)dir); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_free_fromhost); - -int scsc_service_mifintrbit_register_tohost(struct scsc_service *service, void (*handler)(int irq, void *data), void *data) -{ - struct scsc_mx *mx = service->mx; - - SCSC_TAG_DEBUG(MXMAN, "Registering %pS\n", handler); - - return mifintrbit_alloc_tohost(scsc_mx_get_intrbit(mx), handler, data); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_register_tohost); - -int scsc_service_mifintrbit_unregister_tohost(struct scsc_service *service, int which_bit) -{ - struct scsc_mx *mx = service->mx; - - SCSC_TAG_DEBUG(MXMAN, "Deregistering int for bit %d\n", which_bit); - return mifintrbit_free_tohost(scsc_mx_get_intrbit(mx), which_bit); -} -EXPORT_SYMBOL(scsc_service_mifintrbit_unregister_tohost); - -void *scsc_mx_service_mif_addr_to_ptr(struct scsc_service *service, scsc_mifram_ref ref) -{ - struct scsc_mx *mx = service->mx; - - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - return mif_abs->get_mifram_ptr(mif_abs, ref); -} -EXPORT_SYMBOL(scsc_mx_service_mif_addr_to_ptr); - -void *scsc_mx_service_mif_addr_to_phys(struct scsc_service *service, scsc_mifram_ref ref) -{ - struct scsc_mx *mx = service->mx; - - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - if (mif_abs->get_mifram_phy_ptr) - return mif_abs->get_mifram_phy_ptr(mif_abs, ref); - else - return NULL; -} -EXPORT_SYMBOL(scsc_mx_service_mif_addr_to_phys); - -int scsc_mx_service_mif_ptr_to_addr(struct scsc_service *service, void *mem_ptr, scsc_mifram_ref *ref) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - /* Transform native pointer and get mifram_ref type */ - if (mif_abs->get_mifram_ref(mif_abs, mem_ptr, ref)) { - SCSC_TAG_ERR(MXMAN, "ooops somethig went wrong"); - return -ENOMEM; - } - - return 0; -} -EXPORT_SYMBOL(scsc_mx_service_mif_ptr_to_addr); - -int scsc_mx_service_mif_dump_registers(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - struct scsc_mif_abs *mif_abs; - - mif_abs = scsc_mx_get_mif_abs(mx); - - /* Dump registers */ - mif_abs->mif_dump_registers(mif_abs); - - return 0; -} -EXPORT_SYMBOL(scsc_mx_service_mif_dump_registers); - -struct device *scsc_service_get_device(struct scsc_service *service) -{ - return scsc_mx_get_device(service->mx); -} -EXPORT_SYMBOL(scsc_service_get_device); - -struct device *scsc_service_get_device_by_mx(struct scsc_mx *mx) -{ - return scsc_mx_get_device(mx); -} -EXPORT_SYMBOL(scsc_service_get_device_by_mx); - -/* Force a FW panic for test purposes only */ -int scsc_service_force_panic(struct scsc_service *service) -{ - struct mxman *mxman = scsc_mx_get_mxman(service->mx); - - SCSC_TAG_INFO(MXMAN, "%d\n", service->id); - - return mxman_force_panic(mxman); -} -EXPORT_SYMBOL(scsc_service_force_panic); - -#ifdef CONFIG_SCSC_SMAPPER -u16 scsc_service_get_alignment(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - - return mifsmapper_get_alignment(scsc_mx_get_smapper(mx)); -} - -int scsc_service_mifsmapper_alloc_bank(struct scsc_service *service, bool large_bank, u32 entry_size, u16 *entries) -{ - struct scsc_mx *mx = service->mx; - - return mifsmapper_alloc_bank(scsc_mx_get_smapper(mx), large_bank, entry_size, entries); -} -EXPORT_SYMBOL(scsc_service_mifsmapper_alloc_bank); - -void scsc_service_mifsmapper_configure(struct scsc_service *service, u32 granularity) -{ - struct scsc_mx *mx = service->mx; - - mifsmapper_configure(scsc_mx_get_smapper(mx), granularity); -} -EXPORT_SYMBOL(scsc_service_mifsmapper_configure); - -int scsc_service_mifsmapper_write_sram(struct scsc_service *service, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr) -{ - struct scsc_mx *mx = service->mx; - - return mifsmapper_write_sram(scsc_mx_get_smapper(mx), bank, num_entries, first_entry, addr); -} -EXPORT_SYMBOL(scsc_service_mifsmapper_write_sram); - -int scsc_service_mifsmapper_get_entries(struct scsc_service *service, u8 bank, u8 num_entries, u8 *entries) -{ - struct scsc_mx *mx = service->mx; - - return mifsmapper_get_entries(scsc_mx_get_smapper(mx), bank, num_entries, entries); -} -EXPORT_SYMBOL(scsc_service_mifsmapper_get_entries); - -int scsc_service_mifsmapper_free_entries(struct scsc_service *service, u8 bank, u8 num_entries, u8 *entries) -{ - struct scsc_mx *mx = service->mx; - - return mifsmapper_free_entries(scsc_mx_get_smapper(mx), bank, num_entries, entries); -} -EXPORT_SYMBOL(scsc_service_mifsmapper_free_entries); - -int scsc_service_mifsmapper_free_bank(struct scsc_service *service, u8 bank) -{ - struct scsc_mx *mx = service->mx; - - return mifsmapper_free_bank(scsc_mx_get_smapper(mx), bank); -} -EXPORT_SYMBOL(scsc_service_mifsmapper_free_bank); - -u32 scsc_service_mifsmapper_get_bank_base_address(struct scsc_service *service, u8 bank) -{ - struct scsc_mx *mx = service->mx; - - return mifsmapper_get_bank_base_address(scsc_mx_get_smapper(mx), bank); -} -EXPORT_SYMBOL(scsc_service_mifsmapper_get_bank_base_address); -#endif - -#ifdef CONFIG_SCSC_QOS -int scsc_service_pm_qos_add_request(struct scsc_service *service, enum scsc_qos_config config) -{ - struct scsc_mx *mx = service->mx; - - mifqos_add_request(scsc_mx_get_qos(mx), service->id, config); - - return 0; -} -EXPORT_SYMBOL(scsc_service_pm_qos_add_request); - -int scsc_service_pm_qos_update_request(struct scsc_service *service, enum scsc_qos_config config) -{ - struct scsc_mx *mx = service->mx; - - mifqos_update_request(scsc_mx_get_qos(mx), service->id, config); - - return 0; -} -EXPORT_SYMBOL(scsc_service_pm_qos_update_request); - -int scsc_service_pm_qos_remove_request(struct scsc_service *service) -{ - struct scsc_mx *mx = service->mx; - - if (!mx) - return -EIO; - - mifqos_remove_request(scsc_mx_get_qos(mx), service->id); - - return 0; -} -EXPORT_SYMBOL(scsc_service_pm_qos_remove_request); -#endif -#ifdef CONFIG_SCSC_MXLOGGER -/* If there is no service/mxman associated, register the observer as global (will affect all the mx instanes)*/ -/* Users of these functions should ensure that the registers/unregister functions are balanced (i.e. if observer is registed as global, - * it _has_ to unregister as global) */ -int scsc_service_register_observer(struct scsc_service *service, char *name) -{ - struct scsc_mx *mx; - - if (!service) - return mxlogger_register_global_observer(name); - - mx = service->mx; - - if (!mx) - return -EIO; - - return mxlogger_register_observer(scsc_mx_get_mxlogger(mx), name); -} -EXPORT_SYMBOL(scsc_service_register_observer); - -/* If there is no service/mxman associated, unregister the observer as global (will affect all the mx instanes)*/ -int scsc_service_unregister_observer(struct scsc_service *service, char *name) -{ - struct scsc_mx *mx; - - if (!service) - return mxlogger_unregister_global_observer(name); - - mx = service->mx; - - if (!mx) - return -EIO; - - return mxlogger_unregister_observer(scsc_mx_get_mxlogger(mx), name); -} -EXPORT_SYMBOL(scsc_service_unregister_observer); -#endif diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger.h b/drivers/misc/samsung/scsc/scsc_wifilogger.h deleted file mode 100644 index 4eb6769b27a3..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger.h +++ /dev/null @@ -1,199 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef _SCSC_WIFILOGGER_H_ -#define _SCSC_WIFILOGGER_H_ -/** - * Internal Reference docs for WiFi-Logger subsystem - * - * SC-507043-SW -- Android Wi-Fi Logger architecture - * SC-507780-DD -- Android Enhanced Logging - * WiFiLogger Core Driver Requirements and Design - * - * This is the CONSUMER API as implemented by scsc_wifilogger driver: - * the framework and WiFi HAL are the final consumer of WiFi logger provided - * data but this API is directly used by our driver NetLink layer to - * configure and start/stop Android Enhanced Logging - WiFi Logger. - * - * Workflow is as follows: - * - * - framework invokes wifi_logger.h exported methods implemented by WiFi HAL - * - WiFi HAL wifi_logger module translates wifi_logger.h requests into - * NetLink vendor messages dispatched to out driver - * - our SCSC netlink layer driver translates back NetLink received messages - * into invokations of methods exported by this driver into the current - * header file - * - this driver, manages all the basic ring operations, providing: - * + this consumer API used to configure and start/stop the data-consuming - * reader-process that pushes data up to the framework through the NetLink - * channel - * + a producer API that will be used to push data/record into the rings - * + all the machinery needed to create and manage multiple rings - * - * As a consequence this file's types and methods definitions closely resembles - * the interface and types defined in: - * - * hardware/libhardware_legacy/include/hardware_legacy/wifi_logger.h - * hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h - * - * Some function arguments, deemed un-needed in the driver layer, have been - * removed from function prototypes, and all the names have been prefixed - * with "scsc_". - * - * Types' definitions are splitted into scsc_wifilogger_types.h dedicated - * header since they will be used also by core implementation. - * - */ -#include "scsc_wifilogger_types.h" - -/** - * API to collect a firmware version string. - * - Caller is responsible to allocate / free a buffer to retrieve firmware - * version info. - * - Max string will be at most 256 bytes. - */ -wifi_error scsc_wifi_get_firmware_version(char *buffer, int buffer_size); - -/** - * API to collect a driver version string. - * - Caller is responsible to allocate / free a buffer to retrieve driver - * version info. - * - Max string will be at most 256 bytes. - */ -wifi_error scsc_wifi_get_driver_version(char *buffer, int buffer_size); - -/** - * API to get the status of all ring buffers supported by driver. - * - Caller is responsible to allocate / free ring buffer status. - * - Maximum no of ring buffer would be 10. - */ -wifi_error scsc_wifi_get_ring_buffers_status(u32 *num_rings, - struct scsc_wifi_ring_buffer_status *status); - -/** - * API to retrieve the current supportive features. - * - An integer variable is enough to have bit mapping info by caller. - */ -wifi_error scsc_wifi_get_logger_supported_feature_set(unsigned int *support); - - -/** - * API to set/reset the log handler for getting ring data - * - Only a single instance of log handler can be instantiated for each - * ring buffer. - */ -wifi_error scsc_wifi_set_log_handler(on_ring_buffer_data handler, void *ctx); -wifi_error scsc_wifi_reset_log_handler(void); - -/** - * API to set/reset the alert handler for the alert case in Wi-Fi Chip - * - Only a single instance of alert handler can be instantiated. - */ -wifi_error scsc_wifi_set_alert_handler(on_alert handler, void *ctx); -wifi_error scsc_wifi_reset_alert_handler(void); - -/* API for framework to indicate driver has to upload and drain all data - * of a given ring - */ -wifi_error scsc_wifi_get_ring_data(char *ring_name); - -/** - * API to trigger the debug collection. - * Unless his API is invoked - logging is not triggered. - * - Verbose_level 0 corresponds to no collection, - * and it makes log handler stop by no more events from driver. - * - Verbose_level 1 correspond to normal log level, with minimal user impact. - * This is the default value. - * - Verbose_level 2 are enabled when user is lazily trying to reproduce - * a problem, wifi performances and power can be impacted but device should - * not otherwise be significantly impacted. - * - Verbose_level 3+ are used when trying to actively debug a problem. - * - * ring_name represent the name of the ring for which data - * collection shall start. - * - * flags: TBD parameter used to enable/disable specific events - * on a ring - * max_interval: maximum interval in seconds for driver to - * invoke on_ring_buffer_data, - * ignore if zero - * min_data_size: minimum data size in buffer for driver to - * invoke on_ring_buffer_data, - * ignore if zero - */ -wifi_error scsc_wifi_start_logging(u32 verbose_level, u32 flags, u32 max_interval_sec, - u32 min_data_size, char *ring_name); - -/** - * API to collect a firmware memory dump for a given iface by async memdump event. - * - Triggered by Alerthandler, esp. when FW problem or FW health check happens - * - Caller is responsible to store fw dump data into a local, - * e.g., /data/misc/wifi/alertdump-1.bin - */ -wifi_error scsc_wifi_get_firmware_memory_dump(on_firmware_memory_dump handler, void *ctx); - -/** - * API to collect driver state. - * - * Framework will call this API soon before or after (but not - * concurrently with) wifi_get_firmware_memory_dump(). Capturing - * firmware and driver dumps is intended to help identify - * inconsistent state between these components. - * - * - In response to this call, HAL implementation should make one or - * more calls to callbacks.on_driver_memory_dump(). Framework will - * copy data out of the received |buffer|s, and concatenate the - * contents thereof. - * - HAL implemention will indicate completion of the driver memory - * dump by returning from this call. - */ -wifi_error scsc_wifi_get_driver_memory_dump(on_driver_memory_dump handler, void *ctx); - -/** - * API to start packet fate monitoring. - * - Once stared, monitoring should remain active until HAL is unloaded. - * - When HAL is unloaded, all packet fate buffers should be cleared. - */ -wifi_error scsc_wifi_start_pkt_fate_monitoring(void); - -/** - * API to retrieve fates of outbound packets. - * - HAL implementation should fill |tx_report_bufs| with fates of - * _first_ min(n_requested_fates, actual packets) frames - * transmitted for the most recent association. The fate reports - * should follow the same order as their respective packets. - * - HAL implementation may choose (but is not required) to include - * reports for management frames. - * - Packets reported by firmware, but not recognized by driver, - * should be included. However, the ordering of the corresponding - * reports is at the discretion of HAL implementation. - * - Framework may call this API multiple times for the same association. - * - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. - * - Framework will allocate and free the referenced storage. - */ -wifi_error scsc_wifi_get_tx_pkt_fates(wifi_tx_report *tx_report_bufs, - size_t n_requested_fates, - size_t *n_provided_fates); - -/** - * API to retrieve fates of inbound packets. - * - HAL implementation should fill |rx_report_bufs| with fates of - * _first_ min(n_requested_fates, actual packets) frames - * received for the most recent association. The fate reports - * should follow the same order as their respective packets. - * - HAL implementation may choose (but is not required) to include - * reports for management frames. - * - Packets reported by firmware, but not recognized by driver, - * should be included. However, the ordering of the corresponding - * reports is at the discretion of HAL implementation. - * - Framework may call this API multiple times for the same association. - * - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. - * - Framework will allocate and free the referenced storage. - */ -wifi_error scsc_wifi_get_rx_pkt_fates(wifi_rx_report *rx_report_bufs, - size_t n_requested_fates, - size_t *n_provided_fates); - -#endif /*_SCSC_WIFILOGGER_H_*/ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_api.c b/drivers/misc/samsung/scsc/scsc_wifilogger_api.c deleted file mode 100644 index 03647524be82..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_api.c +++ /dev/null @@ -1,261 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#include -#include - -#include "scsc_wifilogger.h" -#include "scsc_wifilogger_core.h" -#include "scsc_wifilogger_internal.h" -#include "scsc_wifilogger_ring_pktfate.h" - -wifi_error scsc_wifi_get_firmware_version(char *buffer, int buffer_size) -{ - SCSC_TAG_DEBUG(WLOG, "\n"); - mxman_get_fw_version(buffer, buffer_size); - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_firmware_version); - -wifi_error scsc_wifi_get_driver_version(char *buffer, int buffer_size) -{ - SCSC_TAG_DEBUG(WLOG, "\n"); - mxman_get_driver_version(buffer, buffer_size); - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_driver_version); - -wifi_error scsc_wifi_get_ring_buffers_status(u32 *num_rings, - struct scsc_wifi_ring_buffer_status *status) -{ - SCSC_TAG_DEBUG(WLOG, "\n"); - if (!scsc_wifilogger_get_rings_status(num_rings, status)) - return WIFI_ERROR_UNINITIALIZED; - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_ring_buffers_status); - -wifi_error scsc_wifi_get_logger_supported_feature_set(unsigned int *support) -{ - SCSC_TAG_DEBUG(WLOG, "\n"); - if (!support) - return WIFI_ERROR_INVALID_ARGS; - *support = scsc_wifilogger_get_features(); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_logger_supported_feature_set); - -wifi_error scsc_wifi_set_log_handler(on_ring_buffer_data handler, void *ctx) -{ - struct scsc_wifi_logger *wl = NULL; - - SCSC_TAG_DEBUG(WLOG, "\n"); - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "Cannot register log_handler on UNINITIALIZED WiFi Logger.\n"); - return WIFI_ERROR_UNINITIALIZED; - } - if (!handler) { - SCSC_TAG_ERR(WLOG, - "Cannot register NULL log_handler for WiFi Logger.\n"); - return WIFI_ERROR_INVALID_ARGS; - } - - mutex_lock(&wl->lock); - if (wl->on_ring_buffer_data_cb) { - SCSC_TAG_ERR(WLOG, - "Log handler already registered...request ignored.\n"); - mutex_unlock(&wl->lock); - return WIFI_SUCCESS; - } - wl->on_ring_buffer_data_cb = handler; - wl->on_ring_buffer_ctx = ctx; - mutex_unlock(&wl->lock); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_set_log_handler); - -wifi_error scsc_wifi_reset_log_handler(void) -{ - struct scsc_wifi_logger *wl = NULL; - - SCSC_TAG_DEBUG(WLOG, "\n"); - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "Cannot reset log_handler on UNINITIALIZED WiFi Logger.\n"); - return WIFI_ERROR_UNINITIALIZED; - } - mutex_lock(&wl->lock); - wl->on_ring_buffer_data_cb = NULL; - wl->on_ring_buffer_ctx = NULL; - mutex_unlock(&wl->lock); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_reset_log_handler); - -wifi_error scsc_wifi_set_alert_handler(on_alert handler, void *ctx) -{ - struct scsc_wifi_logger *wl = NULL; - - SCSC_TAG_DEBUG(WLOG, "\n"); - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "Cannot register alert_handler on UNINITIALIZED WiFi Logger.\n"); - return WIFI_ERROR_UNINITIALIZED; - } - if (!handler) { - SCSC_TAG_ERR(WLOG, - "Cannot register NULL alert_handler for WiFi Logger.\n"); - return WIFI_ERROR_INVALID_ARGS; - } - - mutex_lock(&wl->lock); - if (wl->on_alert_cb) { - SCSC_TAG_ERR(WLOG, - "Alert handler already registered...request ignored.\n"); - mutex_unlock(&wl->lock); - return WIFI_SUCCESS; - } - wl->on_alert_cb = handler; - wl->on_alert_ctx = ctx; - mutex_unlock(&wl->lock); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_set_alert_handler); - -wifi_error scsc_wifi_reset_alert_handler(void) -{ - struct scsc_wifi_logger *wl = NULL; - - SCSC_TAG_DEBUG(WLOG, "\n"); - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "Cannot reset alert_handler on UNINITIALIZED WiFi Logger.\n"); - return WIFI_ERROR_UNINITIALIZED; - } - mutex_lock(&wl->lock); - wl->on_alert_cb = NULL; - wl->on_alert_ctx = NULL; - mutex_unlock(&wl->lock); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_reset_alert_handler); - -wifi_error scsc_wifi_get_ring_data(char *ring_name) -{ - struct scsc_wlog_ring *r; - struct scsc_wifi_logger *wl = NULL; - - SCSC_TAG_DEBUG(WLOG, "\n"); - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "Cannot drain ring %s on UNINITIALIZED WiFi Logger.\n", - ring_name); - return WIFI_ERROR_UNINITIALIZED; - } - - mutex_lock(&wl->lock); - if (!wl->on_ring_buffer_data_cb) - SCSC_TAG_WARNING(WLOG, - "NO log-handler registered. Discarding data while draining ring: %s\n", - ring_name); - mutex_unlock(&wl->lock); - - r = scsc_wifilogger_get_ring_from_name(ring_name); - if (!r) { - SCSC_TAG_ERR(WLOG, - "Ring %s NOT found. Cannot drain.\n", - ring_name); - return WIFI_ERROR_NOT_AVAILABLE; - } - - scsc_wlog_drain_whole_ring(r); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_ring_data); - -wifi_error scsc_wifi_start_logging(u32 verbose_level, u32 flags, u32 max_interval_sec, - u32 min_data_size, char *ring_name) -{ - struct scsc_wlog_ring *r; - - SCSC_TAG_DEBUG(WLOG, "\n"); - r = scsc_wifilogger_get_ring_from_name(ring_name); - if (!r) { - SCSC_TAG_ERR(WLOG, - "Ring %s NOT found. Cannot start logging\n", - ring_name); - return WIFI_ERROR_NOT_AVAILABLE; - } - - return scsc_wlog_start_logging(r, verbose_level, flags, - max_interval_sec, min_data_size); -} -EXPORT_SYMBOL(scsc_wifi_start_logging); - -wifi_error scsc_wifi_get_firmware_memory_dump(on_firmware_memory_dump handler, void *ctx) -{ - char buf[] = "Full FW memory dump NOT available.\n"; - - SCSC_TAG_DEBUG(WLOG, "\n"); - handler(buf, sizeof(buf), ctx); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_firmware_memory_dump); - -wifi_error scsc_wifi_get_driver_memory_dump(on_driver_memory_dump handler, void *ctx) -{ - char buf[] = "Full DRIVER memory dump NOT available.\n"; - - SCSC_TAG_DEBUG(WLOG, "\n"); - handler(buf, sizeof(buf), ctx); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_driver_memory_dump); - -wifi_error scsc_wifi_start_pkt_fate_monitoring(void) -{ - SCSC_TAG_DEBUG(WLOG, "\n"); - scsc_wifilogger_ring_pktfate_start_monitoring(); - - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_start_pkt_fate_monitoring); - -wifi_error scsc_wifi_get_tx_pkt_fates(wifi_tx_report *tx_report_bufs, - size_t n_requested_fates, - size_t *n_provided_fates) -{ - SCSC_TAG_DEBUG(WLOG, "\n"); - scsc_wifilogger_ring_pktfate_get_fates(TX_FATE, tx_report_bufs, - n_requested_fates, n_provided_fates); - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_tx_pkt_fates); - -wifi_error scsc_wifi_get_rx_pkt_fates(wifi_rx_report *rx_report_bufs, - size_t n_requested_fates, - size_t *n_provided_fates) -{ - SCSC_TAG_DEBUG(WLOG, "\n"); - scsc_wifilogger_ring_pktfate_get_fates(RX_FATE, rx_report_bufs, - n_requested_fates, n_provided_fates); - return WIFI_SUCCESS; -} -EXPORT_SYMBOL(scsc_wifi_get_rx_pkt_fates); diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_core.c b/drivers/misc/samsung/scsc/scsc_wifilogger_core.c deleted file mode 100644 index 24afb406ea78..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_core.c +++ /dev/null @@ -1,470 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -/* Uses */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Implements */ -#include "scsc_wifilogger_core.h" - -static atomic_t next_ring_id; - -static void wlog_drain_worker(struct work_struct *work) -{ - struct scsc_wlog_ring *r; - - r = container_of(work, struct scsc_wlog_ring, drain_work); - - if (r && r->ops.drain_ring) - r->ops.drain_ring(r, r->flushing ? r->st.rb_byte_size : DEFAULT_DRAIN_CHUNK_SZ(r)); -} - -static void drain_timer_callback(unsigned long data) -{ - struct scsc_wlog_ring *r = (struct scsc_wlog_ring *)data; - - SCSC_TAG_DBG4(WLOG, "TIMER DRAIN : %p\n", r); - /* we should kick the workqueue here...no sleep */ - queue_work(r->drain_workq, &r->drain_work); - - if (r->st.verbose_level && r->max_interval_sec) { - mod_timer(&r->drain_timer, - jiffies + msecs_to_jiffies(r->max_interval_sec * 1000)); - SCSC_TAG_DBG4(WLOG, "TIMER RELOADED !!!\n"); - } -} - -static int wlog_ring_init(struct scsc_wlog_ring *r) -{ - /* Allocate buffer and spare area */ - r->buf = kzalloc(r->st.rb_byte_size + MAX_RECORD_SZ, GFP_KERNEL); - if (!r->buf) - return -ENOMEM; - r->drain_sz = DRAIN_BUF_SZ; - r->drain_buf = kzalloc(r->drain_sz, GFP_KERNEL); - if (!r->drain_buf) { - kfree(r->buf); - return -ENOMEM; - } - mutex_init(&r->drain_lock); - - r->drain_workq = create_workqueue("wifilogger"); - INIT_WORK(&r->drain_work, wlog_drain_worker); - setup_timer(&r->drain_timer, drain_timer_callback, (unsigned long)r); - - r->st.ring_id = atomic_read(&next_ring_id); - atomic_inc(&next_ring_id); - - SCSC_TAG_DBG3(WLOG, "Workers initialized for ring[%p]: %s\n", - r, r->st.name); - - return 0; -} - -static void wlog_ring_finalize(struct scsc_wlog_ring *r) -{ - if (!r) - return; - - cancel_work_sync(&r->drain_work); - del_timer_sync(&r->drain_timer); - destroy_workqueue(r->drain_workq); - - r->initialized = false; - kfree(r->drain_buf); - kfree(r->buf); - r->buf = NULL; -} - -static wifi_error wlog_get_ring_status(struct scsc_wlog_ring *r, - struct scsc_wifi_ring_buffer_status *status) -{ - if (!r || !status) - return WIFI_ERROR_INVALID_ARGS; - //TODO locking SRCU ? - *status = r->st; - - return WIFI_SUCCESS; -} - -static int wlog_read_records(struct scsc_wlog_ring *r, u8 *buf, - size_t blen, u32 *records, - struct scsc_wifi_ring_buffer_status *status) -{ - u16 read_bytes = 0, rec_sz = 0; - u32 got_records = 0, req_records = -1; - - if (scsc_wlog_ring_is_flushing(r)) - return 0; - - /** - * req_records has been loaded with a max u32 value by default - * on purpose...if a max number of records is provided in records - * update req_records accordingly - */ - if (records) - req_records = *records; - /** - * We have ONLY ONE READER at any time that consumes data, impersonated - * here by the drain_ring drainer callback, whose read-ops are ensured - * atomic by the drain_lock mutex: this will guard against races - * between the periodic-drain worker and the threshold-drain procedure - * triggered by the write itself. - * - * But we want also to guard against any direct read_record invokation - * like in test rings via debugfs so we add a read spinlock: this last - * won't lead to any contention here anyway most of the time in a - * real scenario so the same reason we don't need either any irqsave - * spinlock version....so latency also is not impacted. - */ - raw_spin_lock(&r->rlock); - while (!scsc_wlog_is_ring_empty(r) && got_records < req_records) { - rec_sz = REC_SZ(r, RPOS(r)); - if (read_bytes + rec_sz > blen) - break; - /** - * Rollover is transparent on read...last written material in - * spare is still there... - */ - memcpy(buf + read_bytes, REC_START(r, RPOS(r)), rec_sz); - read_bytes += rec_sz; - r->st.read_bytes += rec_sz; - got_records++; - } - if (status) - *status = r->st; - raw_spin_unlock(&r->rlock); - - if (records) - *records = got_records; - SCSC_TAG_DBG4(WLOG, "BytesRead:%d -- RecordsRead:%d\n", - read_bytes, got_records); - - return read_bytes; -} - -static int wlog_default_ring_drainer(struct scsc_wlog_ring *r, size_t drain_sz) -{ - int rval = 0, drained_bytes = 0; - size_t chunk_sz = drain_sz <= r->drain_sz ? drain_sz : r->drain_sz; - struct scsc_wifi_ring_buffer_status ring_status = {}; - - /* An SRCU on callback here would better */ - mutex_lock(&r->drain_lock); - do { - /* drain ... consumes data */ - rval = r->ops.read_records(r, r->drain_buf, chunk_sz, NULL, &ring_status); - /* and push...if any callback defined */ - if (!r->flushing) { - mutex_lock(&r->wl->lock); - if (rval > 0 && r->wl->on_ring_buffer_data_cb) { - SCSC_TAG_DEBUG(WLOG, - "Invoking registered log_handler:%p to drain %d bytes\n", - r->wl->on_ring_buffer_data_cb, rval); - r->wl->on_ring_buffer_data_cb(r->st.name, r->drain_buf, rval, - &ring_status, r->wl->on_ring_buffer_ctx); - SCSC_TAG_DBG4(WLOG, "Callback processed %d bytes\n", rval); - } - mutex_unlock(&r->wl->lock); - } - drained_bytes += rval; - } while (rval && drained_bytes <= drain_sz); - SCSC_TAG_DBG3(WLOG, "%s %d bytes\n", (r->flushing) ? "Flushed" : "Drained", - drained_bytes); - - /* Execute flush if required... */ - if (r->flushing) { - unsigned long flags; - - /* Inhibit writers momentarily */ - raw_spin_lock_irqsave(&r->wlock, flags); - r->dropped = 0; - r->st.written_records = 0; - r->st.read_bytes = r->st.written_bytes = 0; - r->flushing = false; - raw_spin_unlock_irqrestore(&r->wlock, flags); - SCSC_TAG_INFO(WLOG, "Ring '%s' flushed.\n", r->st.name); - } - mutex_unlock(&r->drain_lock); - - return drained_bytes; -} - -/** - * A generic write that takes care to build the final payload created - * concatenating: - * - the common record-header - * - an optionally provided ring_hdr - * - the provided payload buf - * - * The optional header is passed down as a separate parameters to avoid - * unnecessary intermediate copies: this function will copy all the bits - * in place directly into the proper calculated ring position. - * - * By design a read-end-point is always provided by the framework - * (in terms of netlink channels towards the WiFi-HAL) so we spawn a - * configurable reader-worker upon start of logging, and the same reader - * is also invoked when ring is running out of space: for these reasons - * the ring is meant NOT to overwrite itself ever. - * - * If NO periodic reader is spawned NOR a min_data_size threshold was - * specified to force kick the periodic drainer, we could just end-up - * filling up the ring: in that case we just drop and account for it. - * - * Data is drained and pushed periodically upstream using the - * on_ring_buffer_data_cb if any provided and periodic drain was - * configured. - * - * @r: the referenced ring - * @buf: payload - * @blen: payload_sz - * @ring_hdr: upper-layer-record-header - * @hlen: upper-layer-record-header length - * @verbose_level: loglevel for this message (to be checked against) - * @timestamp: a providewd timestamp (if any). If zero a timestamp will be - * calculated. - * - * Final injected record will be composed as follows: - * - * |common_hdr|ring_hdr|buf| - * - * where the common header is compued and filled in by this function, and the - * provided additional upper-layer header ring_hdr could be not provided. - * - * THIS BASIC RING OPERATION IS THE WORKHORSE USED BY THE PRODUCER API IMPLEMENTED - * BY REAL RINGS, AND AS SUCH COULD BE INVOKED FROM ANY CONTEXTS...SO IT MUST NOT SLEEP. - */ -static int wlog_write_record(struct scsc_wlog_ring *r, u8 *buf, size_t blen, - void *ring_hdr, size_t hlen, u32 verbose_level, u64 timestamp) -{ - u8 *start = NULL; - u16 chunk_sz; - unsigned long flags; - - if (scsc_wlog_ring_is_flushing(r)) - return 0; - - /* Just drop messages above configured verbose level. 0 is disabled */ - if (!scsc_wlog_is_message_allowed(r, verbose_level)) - return 0; - - //TODO Account for missing timestamp - chunk_sz = sizeof(struct scsc_wifi_ring_buffer_entry) + hlen + blen; - if (chunk_sz > MAX_RECORD_SZ) { - SCSC_TAG_WARNING(WLOG, "Dropping record exceeding %d bytes\n", - chunk_sz); - return 0; - } - - raw_spin_lock_irqsave(&r->wlock, flags); - /** - * Are there enough data to drain ? - * if so...drain...queueing work.... - * if not (min_data_size == 0) just do nothing - */ - if (!r->drop_on_full && r->min_data_size && - AVAIL_BYTES(r) >= r->min_data_size) - queue_work(r->drain_workq, &r->drain_work); - /** - * If no min_data_size was specified, NOR a periodic read-worker - * was configured (i.e. max_interval_sec == 0), we could end up - * filling up the ring...in that case just drop...accounting for it. - * - * This is the case when packet_fate rings fills up... - */ - if (!CAN_FIT(r, chunk_sz)) { - SCSC_TAG_DBG4(WLOG, "[%s]:: dropped %zd bytes\n", - r->st.name, blen + hlen); - r->dropped += blen + hlen; - raw_spin_unlock_irqrestore(&r->wlock, flags); - return 0; - } - - start = REC_START(r, WPOS(r)); - REC_HEADER_FILL(start, hlen + blen, timestamp, (u8)r->st.flags, r->type); - start += sizeof(struct scsc_wifi_ring_buffer_entry); - if (hlen) { - memcpy(start, ring_hdr, hlen); - start += hlen; - } - if (blen) - memcpy(start, buf, blen); - /* Account for rollover using spare area at end of ring... */ - if (start + blen > BUF_END(r)) - memcpy(BUF_START(r), BUF_END(r), start + blen - BUF_END(r)); - r->st.written_bytes += chunk_sz; - r->st.written_records++; - raw_spin_unlock_irqrestore(&r->wlock, flags); - - return chunk_sz; -} - -static int wlog_default_ring_config_change(struct scsc_wlog_ring *r, - u32 verbose_level, u32 flags, - u32 max_interval_sec, - u32 min_data_size) -{ - u32 old_interval_sec; - - SCSC_TAG_DEBUG(WLOG, "Ring: %s -- configuration change.\n", - r->st.name); - - r->min_data_size = min_data_size; - old_interval_sec = r->max_interval_sec; - r->max_interval_sec = max_interval_sec; - - if (r->state == RING_STATE_SUSPEND && r->st.verbose_level) { - /* Restarting timeri where required ... - * it will take care to queue_work back. - */ - if (r->max_interval_sec) - mod_timer(&r->drain_timer, - jiffies + msecs_to_jiffies(r->max_interval_sec * 1000)); - r->state = RING_STATE_ACTIVE; - SCSC_TAG_INFO(WLOG, "ACTIVATED ring: %s\n", r->st.name); - } else if (r->state == RING_STATE_ACTIVE && !r->st.verbose_level) { - /* Stop timer, cancel pending work */ - del_timer_sync(&r->drain_timer); - cancel_work_sync(&r->drain_work); - r->state = RING_STATE_SUSPEND; - SCSC_TAG_INFO(WLOG, "SUSPENDED ring: %s\n", r->st.name); - } else if (r->state == RING_STATE_ACTIVE) { - if (old_interval_sec != r->max_interval_sec) { - if (!r->max_interval_sec) - del_timer_sync(&r->drain_timer); - else - mod_timer(&r->drain_timer, - jiffies + msecs_to_jiffies(r->max_interval_sec * 1000)); - } - SCSC_TAG_INFO(WLOG, "RECONFIGURED ring: %s\n", r->st.name); - } - - return 0; -} - -static wifi_error wlog_start_logging(struct scsc_wlog_ring *r, - u32 verbose_level, u32 flags, - u32 max_interval_sec, - u32 min_data_size) -{ - if (!r) - return WIFI_ERROR_INVALID_ARGS; - - scsc_wlog_ring_change_verbosity(r, verbose_level); - wlog_default_ring_config_change(r, verbose_level, flags, - max_interval_sec, min_data_size); - - return WIFI_SUCCESS; -} - -static struct scsc_wlog_ring_ops default_ring_ops = { - .init = NULL, - .finalize = NULL, - .get_ring_status = wlog_get_ring_status, - .read_records = wlog_read_records, - .write_record = wlog_write_record, - .loglevel_change = NULL, - .drain_ring = wlog_default_ring_drainer, - .start_logging = wlog_start_logging, -}; - -void scsc_wlog_ring_destroy(struct scsc_wlog_ring *r) -{ - if (!r || r->registered) { - SCSC_TAG_ERR(WLOG, "Cannot destroy ring r:%p\n", r); - return; - } - /* If initialized call custom finalizer at first..reverse order */ - if (r->initialized && r->ops.finalize) - r->ops.finalize(r); - wlog_ring_finalize(r); - kfree(r); -} - -struct scsc_wlog_ring *scsc_wlog_ring_create(char *ring_name, u32 flags, - u8 type, u32 size, - unsigned int features_mask, - init_cb init, finalize_cb fini, - void *priv) -{ - struct scsc_wlog_ring *r = NULL; - - WARN_ON(!ring_name || !size); - - r = kzalloc(sizeof(*r), GFP_KERNEL); - if (!r) - return r; - r->type = type; - r->st.flags = flags; - r->st.rb_byte_size = size; - if (snprintf(r->st.name, RING_NAME_SZ - 1, "%s", ring_name) >= RING_NAME_SZ) - SCSC_TAG_WARNING(WLOG, "Ring name too long...truncated to: %s\n", - r->st.name); - /* Setup defaults and configure init finalize if any provided */ - memcpy(&r->ops, &default_ring_ops, sizeof(struct scsc_wlog_ring_ops)); - r->ops.init = init; - r->ops.finalize = fini; - r->priv = priv; - /* Basic common initialization is called first */ - if (wlog_ring_init(r)) { - SCSC_TAG_ERR(WLOG, - "Wi-Fi Logger Ring %s basic initialization failed.\n", - r->st.name); - kfree(r); - return NULL; - } - if (r->ops.init) { - if (r->ops.init(r)) { - SCSC_TAG_DBG4(WLOG, - "Ring %s custom init completed\n", - r->st.name); - } else { - SCSC_TAG_ERR(WLOG, - "Ring %s custom init FAILED !\n", - r->st.name); - scsc_wlog_ring_destroy(r); - return NULL; - } - } - r->features_mask = features_mask; - raw_spin_lock_init(&r->rlock); - raw_spin_lock_init(&r->wlock); - r->initialized = true; - SCSC_TAG_DEBUG(WLOG, "Ring '%s' initialized.\n", r->st.name); - - return r; -} - -int scsc_wlog_register_loglevel_change_cb(struct scsc_wlog_ring *r, - int (*callback)(struct scsc_wlog_ring *r, u32 new_loglevel)) -{ - if (!callback) - r->ops.loglevel_change = NULL; - else - r->ops.loglevel_change = callback; - - return 0; -} - -int scsc_wlog_drain_whole_ring(struct scsc_wlog_ring *r) -{ - SCSC_TAG_INFO(WLOG, "Draining whole ring %s\n", r->st.name); - return r->ops.drain_ring(r, r->st.rb_byte_size); -} - -void scsc_wlog_flush_ring(struct scsc_wlog_ring *r) -{ - r->flushing = true; - /* kick the workq...which will take care of flushing */ - queue_work(r->drain_workq, &r->drain_work); -} diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_core.h b/drivers/misc/samsung/scsc/scsc_wifilogger_core.h deleted file mode 100644 index fab28cb8e5f9..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_core.h +++ /dev/null @@ -1,270 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef _SCSC_WIFILOGGER_CORE_H_ -#define _SCSC_WIFILOGGER_CORE_H_ -/** - * @file - * - * Implements a basic ring abstraction to be used as a common foundation - * upon which all the Wi-Fi Logger real rings are built. - * - * It will provide: - * - * - the basic record header common to all rings' flavours as defined in - * scsc_wifilogger_types.h::struct scsc_wifi_ring_buffer_entry - * - * | entry | flags | type | timestamp | - * - * - a set of common basic rings' methods: default_ring_ops - * - * - a common periodic worker used to periodically drain the rings using - * one of the above operations (when configured to do so) - * - * General Ring Architecture - * ------------------------- - * The ring is constituted by a buffer of contiguos memory of specified - * size followed by a spare area of MAX_RECORD_SZ; this latter area is used - * when a record would not fit the physical end of the ring buffer and would - * be going to wrap around: in a such a case we simply write down the record - * content and let it spill over into the spare area; we'll then take care - * to copy the overflown part from the spare area into the start of the - * physical buffer. For this reason a limit of MAX_RECORD_SZ length is - * enforced on write. - * - * Ring status is maintained inside that - * is a well known and defined structure defined in scsc_wifilogger_types.h; - * such structure format is expected by Framework itself when it queries for - * ring status using Wi-Fi HAL. - * Such structure contains also the @read_bytes and @written_bytes counters - * needed for all the ring mechanics based on modulo-ring-size aritmethic. - * Modulo arithmethic is achieved without using the % operator itself so ring - * is expected to be of power-of-two size. - * - * Ring's basic operations are defined as follows: - * - MULTIPLE concurrent writers are expected (and handled) - * - * - Only ONE active reader is expected at any time: such a reader could act - * out of the periodic reader worker or triggered by a write operation. - * - * - each ring read-behavior is configured by two params: - * + min_data_size: the minimum amount of available data that should trigger - * a read. Ignored if zero. - * + max_interval_sec: periodic-reader interval in seconds. Ignored if zero. - * - * NOTE THAT if both the above params are configured as zero, no periodic or - * threshold reading process will be performed and, in absence of any kind of - * polling-read mechanism, the ring would finally FILL-UP: in such a case all - * the data received once the ring is full will be DROPPED. - * This behavior fits the pkt_fate use case scenario. - */ - -#include "scsc_wifilogger_types.h" -#include "scsc_wifilogger_internal.h" - -#define DRAIN_BUF_SZ 4096 - -#define BUF_SZ(r) ((r)->st.rb_byte_size) -#define BUF_START(r) ((r)->buf) -#define BUF_END(r) ((r)->buf + BUF_SZ(r)) -#define AVAIL_BYTES(r) ((r)->st.written_bytes - (r)->st.read_bytes) - -/** - * Avoid % when calculating ring-relative position - * Ring SIZE MUST BE A POWER OF TWO....currently is enforced in - * WiFi-Logger code since there's no way (API) to set the rings' sizes. - */ -#define RPOS(r) \ - ((r)->st.read_bytes & (BUF_SZ(r) - 1)) - -#define WPOS(r) \ - ((r)->st.written_bytes & (BUF_SZ(r) - 1)) - -#define WPOS_INC(r, bytes) \ - (((r)->st.written_bytes + (bytes)) & (BUF_SZ(r) - 1)) - -#define REC_PAYLOAD_SZ(r, pos) \ - (*((u16 *)((r)->buf + (pos)))) - -#define REC_SZ(r, pos) \ - (REC_PAYLOAD_SZ(r, pos) + sizeof(struct scsc_wifi_ring_buffer_entry)) - -#define REC_START(r, pos) ((r)->buf + (pos)) - -#define IS_EMPTY(r) \ - ((r)->st.read_bytes == (r)->st.written_bytes) - -#define CAN_FIT(r, bytes) \ - (bytes < BUF_SZ(r) && \ - (IS_EMPTY(r) || \ - (WPOS(r) < RPOS(r) && WPOS(r) + (bytes) < RPOS(r)) || \ - (WPOS(r) > RPOS(r) && (WPOS(r) + (bytes) < BUF_SZ(r) || WPOS_INC(r, bytes) < RPOS(r))))) - -#define REC_HEADER_FILL(ptr, payload_sz, rtimestamp, rflags, rtype) \ - do { \ - struct scsc_wifi_ring_buffer_entry *h = \ - (struct scsc_wifi_ring_buffer_entry *)(ptr); \ - \ - h->entry_size = (payload_sz); \ - h->flags |= (rflags) | RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP; \ - h->type = (rtype); \ - h->timestamp = (rtimestamp) ?: local_clock();\ - } while (0) - -#define MINIMUM_DRAIN_CHUNK_BYTES 1024 -#define DEFAULT_DRAIN_CHUNK_SZ(r) ((r)->st.rb_byte_size / 2) -#define FORCE_DRAIN_CHUNK_SZ(r) ((r)->st.rb_byte_size / 4) -#define MAX_RECORD_SZ 8192 - -enum { - RING_STATE_SUSPEND, - RING_STATE_ACTIVE -}; - -struct scsc_wlog_ring; - -typedef bool (*init_cb)(struct scsc_wlog_ring *r); -typedef bool (*finalize_cb)(struct scsc_wlog_ring *r); - -struct scsc_wlog_ring_ops { - init_cb init; - finalize_cb finalize; - - wifi_error (*get_ring_status)(struct scsc_wlog_ring *r, - struct scsc_wifi_ring_buffer_status *status); - int (*read_records)(struct scsc_wlog_ring *r, u8 *buf, size_t blen, - u32 *records, struct scsc_wifi_ring_buffer_status *status); - int (*write_record)(struct scsc_wlog_ring *r, u8 *buf, size_t blen, - void *hdr, size_t hlen, u32 verbose_level, u64 timestamp); - int (*loglevel_change)(struct scsc_wlog_ring *r, u32 new_loglevel); - int (*drain_ring)(struct scsc_wlog_ring *r, size_t drain_sz); - wifi_error (*start_logging)(struct scsc_wlog_ring *r, u32 verbose_level, - u32 flags, u32 max_interval_sec, - u32 min_data_size); -}; - -struct scsc_wlog_ring { - bool initialized; - bool registered; - bool flushing; - bool drop_on_full; - u8 state; - - u8 *buf; - unsigned int features_mask; - u8 type; - u32 min_data_size; - u32 max_interval_sec; - u32 dropped; - u32 *verbosity; - raw_spinlock_t rlock, wlock; - struct scsc_wifi_ring_buffer_status st; - - u8 *drain_buf; - size_t drain_sz; - struct mutex drain_lock; - struct timer_list drain_timer; - struct work_struct drain_work; - struct workqueue_struct *drain_workq; - - struct scsc_wlog_ring_ops ops; - - void *priv; - - struct scsc_wifi_logger *wl; -}; - -struct scsc_wlog_ring *scsc_wlog_ring_create(char *ring_name, u32 flags, - u8 type, u32 size, - unsigned int features_mask, - init_cb init, finalize_cb fini, - void *priv); - -void scsc_wlog_ring_destroy(struct scsc_wlog_ring *r); - -int scsc_wlog_register_loglevel_change_cb(struct scsc_wlog_ring *r, - int (*callback)(struct scsc_wlog_ring *r, - u32 new_loglevel)); - -int scsc_wlog_drain_whole_ring(struct scsc_wlog_ring *r); - -static inline bool scsc_wlog_is_ring_empty(struct scsc_wlog_ring *r) -{ - return r->st.written_bytes == r->st.read_bytes; -} - -static inline wifi_error scsc_wlog_get_ring_status(struct scsc_wlog_ring *r, - struct scsc_wifi_ring_buffer_status *status) -{ - if (!r) - return WIFI_ERROR_INVALID_ARGS; - - return r->ops.get_ring_status(r, status); -} - -static inline bool scsc_wlog_is_message_allowed(struct scsc_wlog_ring *r, u32 verbose_level) -{ - return r->st.verbose_level && verbose_level <= r->st.verbose_level; -} - -static inline int scsc_wlog_read_records(struct scsc_wlog_ring *r, u8 *buf, size_t blen) -{ - return r->ops.read_records(r, buf, blen, NULL, NULL); -} - -static inline int scsc_wlog_read_max_records(struct scsc_wlog_ring *r, u8 *buf, - size_t blen, u32 *max_records) -{ - return r->ops.read_records(r, buf, blen, max_records, NULL); -} - -static inline int scsc_wlog_write_record(struct scsc_wlog_ring *r, u8 *buf, size_t blen, - void *hdr, size_t hlen, u32 verbose_level, u64 timestamp) -{ - return r->ops.write_record(r, buf, blen, hdr, hlen, verbose_level, timestamp); -} - -static inline wifi_error scsc_wlog_start_logging(struct scsc_wlog_ring *r, - u32 verbose_level, u32 flags, - u32 max_interval_sec, u32 min_data_size) -{ - return r->ops.start_logging(r, verbose_level, flags, max_interval_sec, min_data_size); -} - -static inline void scsc_wlog_ring_set_drop_on_full(struct scsc_wlog_ring *r) -{ - r->drop_on_full = true; -} - -static inline void scsc_wlog_register_verbosity_reference(struct scsc_wlog_ring *r, u32 *verbose_ref) -{ - r->verbosity = verbose_ref; -} - -static inline bool scsc_wlog_ring_is_flushing(struct scsc_wlog_ring *r) -{ - if (!r->flushing) - return false; - - SCSC_TAG_DBG4(WLOG, "Ring is flushing..abort pending read/write\n"); - return true; -} - -static inline void scsc_wlog_ring_change_verbosity(struct scsc_wlog_ring *r, u32 verbose_level) -{ - if (r->st.verbose_level != verbose_level) { - if (r->ops.loglevel_change) - r->ops.loglevel_change(r, verbose_level); - r->st.verbose_level = verbose_level; - if (r->verbosity) - *r->verbosity = r->st.verbose_level; - SCSC_TAG_INFO(WLOG, "Ring: %s -- verbose_level changed to: %d\n", - r->st.name, r->st.verbose_level); - } -} - -void scsc_wlog_flush_ring(struct scsc_wlog_ring *r); - -#endif /*_SCSC_WIFI_LOGGER_CORE_H_*/ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_debugfs.c b/drivers/misc/samsung/scsc/scsc_wifilogger_debugfs.c deleted file mode 100644 index 7ab5ff025864..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_debugfs.c +++ /dev/null @@ -1,439 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#include -#include "scsc_wifilogger_debugfs.h" -#include "scsc_wifilogger_ring_pktfate.h" - -struct dentry *scsc_wlog_debugfs_global_root; - -int dfs_open(struct inode *ino, struct file *filp) -{ - if (!filp->private_data) { - filp->private_data = ino->i_private; - if (!filp->private_data) - return -EFAULT; - } - return 0; -} - -int dfs_release(struct inode *ino, struct file *filp) -{ - return 0; -} - -#define SCSC_RING_TEST_STAT_SZ 512 - -static ssize_t dfs_stats_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - int slen = 0; - char statstr[SCSC_RING_TEST_STAT_SZ] = {}; - struct scsc_ring_test_object *rto = filp->private_data; - - slen = snprintf(statstr, SCSC_RING_TEST_STAT_SZ, - "[%s]:: len:%d state:%d verbose:%d min_data_size:%d max_interval_sec:%d drop_on_full:%d\n" - "\tunread:%d written:%d read:%d written_records:%d dropped:%d buf:%p\n", - rto->r->st.name, rto->r->st.rb_byte_size, rto->r->state, - rto->r->st.verbose_level, rto->r->min_data_size, - rto->r->max_interval_sec, rto->r->drop_on_full, - rto->r->st.written_bytes - rto->r->st.read_bytes, - rto->r->st.written_bytes, rto->r->st.read_bytes, - rto->r->st.written_records, rto->r->dropped, rto->r->buf); - if (slen >= 0 && *f_pos < slen) { - count = (count <= slen - *f_pos) ? count : (slen - *f_pos); - if (copy_to_user(ubuf, statstr + *f_pos, count)) - return -EFAULT; - *f_pos += count; - } else { - count = 0; - } - return count; -} - -const struct file_operations stats_fops = { - .owner = THIS_MODULE, - .open = dfs_open, - .read = dfs_stats_read, - .release = dfs_release, -}; - -#ifdef CONFIG_SCSC_WIFILOGGER_TEST -static int dfs_read_record_open(struct inode *ino, struct file *filp) -{ - int ret; - struct scsc_ring_test_object *rto; - - ret = dfs_open(ino, filp); - if (ret) - return ret; - - rto = filp->private_data; - if (!mutex_trylock(&rto->readers_lock)) { - SCSC_TAG_ERR(WLOG, - "Failed to get readers mutex...ONLY one reader allowed !!!\n"); - dfs_release(ino, filp); - return -EPERM; - } - /* NO Log handler here...only raise verbosity */ - scsc_wifi_start_logging(1, 0x00, 0, 8192, rto->r->st.name); - - return ret; -} - -static int dfs_read_record_release(struct inode *ino, struct file *filp) -{ - struct scsc_ring_test_object *rto = filp->private_data; - - /* Stop logging ... verbosity 0 */ - scsc_wifi_start_logging(0, 0x00, 0, 8192, rto->r->st.name); - mutex_unlock(&rto->readers_lock); - SCSC_TAG_DEBUG(WLOG, "Readers mutex released.\n"); - - return dfs_release(ino, filp); -} - -static ssize_t dfs_read_record(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - int ret; - struct scsc_ring_test_object *rto; - - if (!filp->private_data) - return -EINVAL; - rto = filp->private_data; - - while (scsc_wlog_is_ring_empty(rto->r)) { - if (wait_event_interruptible(rto->rw_wq, - !scsc_wlog_is_ring_empty(rto->r))) - return -ERESTARTSYS; - } - ret = scsc_wlog_read_records(rto->r, rto->rbuf, rto->bsz); - count = ret <= count ? ret : count; - if (copy_to_user(ubuf, rto->rbuf, count)) - return -EFAULT; - *f_pos += count; - - return count; -} - -const struct file_operations read_record_fops = { - .owner = THIS_MODULE, - .open = dfs_read_record_open, - .read = dfs_read_record, - .release = dfs_read_record_release, -}; - -static void on_ring_test_data_cb(char *ring_name, char *buf, int bsz, - struct scsc_wifi_ring_buffer_status *status, - void *ctx) -{ - struct scsc_ring_test_object *a_rto, *head_rto = ctx; - - a_rto = kzalloc(sizeof(*a_rto), GFP_KERNEL); - if (!a_rto) - return; - a_rto->rbuf = kmalloc(bsz, GFP_KERNEL); - if (!a_rto->rbuf) { - kfree(a_rto); - return; - } - /* copy and pass over into a list to simulate a channel */ - memcpy(a_rto->rbuf, buf, bsz); - a_rto->bsz = bsz; - list_add_tail(&a_rto->elem, &head_rto->elem); - wake_up_interruptible(&head_rto->drain_wq); -} - -static int dfs_read_open(struct inode *ino, struct file *filp) -{ - int ret; - struct scsc_ring_test_object *rto; - - ret = dfs_open(ino, filp); - if (ret) - return ret; - - /* Filp private data NOW contains rto */ - rto = filp->private_data; - if (!mutex_trylock(&rto->readers_lock)) { - SCSC_TAG_ERR(WLOG, - "Failed to get readers mutex...ONLY one reader allowed !!!\n"); - dfs_release(ino, filp); - return -EPERM; - } - - SCSC_TAG_DEBUG(WLOG, - "DebugFS Read opened...setting handlers...starting logging on: %s\n", - rto->r->st.name); - scsc_wifi_set_log_handler(on_ring_test_data_cb, rto); - scsc_wifi_start_logging(1, 0x00, 2, 8192, rto->r->st.name); - - return ret; -} - -static ssize_t dfs_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - size_t ret_count = 0; - struct list_head *pos = NULL, *tlist = NULL; - struct scsc_ring_test_object *head_rto, *a_rto; - - if (!filp->private_data) - return -EINVAL; - head_rto = filp->private_data; - - while (list_empty(&head_rto->elem)) { - if (wait_event_interruptible(head_rto->drain_wq, !list_empty(&head_rto->elem))) - return -ERESTARTSYS; - } - - list_for_each_safe(pos, tlist, &head_rto->elem) { - a_rto = list_entry(pos, struct scsc_ring_test_object, elem); - SCSC_TAG_DEBUG(WLOG, "Processing list item: %p\n", a_rto); - if (!a_rto || ret_count + a_rto->bsz >= count) { - SCSC_TAG_DEBUG(WLOG, "BREAK OUT on:%p\n", a_rto); - list_del(pos); - if (a_rto) { - kfree(a_rto->rbuf); - kfree(a_rto); - } - break; - } - if (copy_to_user(ubuf + ret_count, a_rto->rbuf, a_rto->bsz)) - return -EFAULT; - ret_count += a_rto->bsz; - list_del(pos); - kfree(a_rto->rbuf); - kfree(a_rto); - } - *f_pos += ret_count; - - return count; -} - -static int dfs_read_release(struct inode *ino, struct file *filp) -{ - int ret; - struct scsc_ring_test_object *head_rto, *a_rto; - - head_rto = filp->private_data; - if (head_rto) { - struct list_head *pos = NULL, *tlist = NULL; - - list_for_each_safe(pos, tlist, &head_rto->elem) { - a_rto = list_entry(pos, struct scsc_ring_test_object, elem); - list_del(pos); - if (a_rto) { - kfree(a_rto->rbuf); - kfree(a_rto); - a_rto = NULL; - } - } - } - - ret = dfs_read_record_release(ino, filp); - scsc_wifi_reset_log_handler(); - - return ret; -} - -const struct file_operations read_fops = { - .owner = THIS_MODULE, - .open = dfs_read_open, - .read = dfs_read, - .release = dfs_read_release, -}; - -#define BUF_LEN 16 -static ssize_t dfs_verbose_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - char buf[BUF_LEN] = {}; - struct scsc_ring_test_object *rto; - - if (!filp->private_data) - return -EINVAL; - rto = filp->private_data; - - count = snprintf(buf, BUF_LEN, "%d\n", rto->r->st.verbose_level); - if (copy_to_user(ubuf, buf, count)) - return -EFAULT; - /* emit EOF after having spitted the value once */ - count = !*f_pos ? count : 0; - *f_pos += count; - - return count; -} - -static ssize_t dfs_verbose_write(struct file *filp, const char __user *ubuf, - size_t count, loff_t *f_pos) -{ - char buf[BUF_LEN] = {}; - size_t written; - unsigned long verb; - struct scsc_ring_test_object *rto; - - if (!filp->private_data) - return -EINVAL; - rto = filp->private_data; - - count = count < BUF_LEN ? count : BUF_LEN - 1; - if (copy_from_user(buf, ubuf, count)) - return -EINVAL; - if (!kstrtoul((const char *)buf, 10, &verb)) - scsc_wlog_ring_change_verbosity(rto->r, verb); - written = strlen(buf); - *f_pos += written; - - SCSC_TAG_DEBUG(WLOG, "Changed verbosity on ring %s to %d\n", - rto->r->st.name, rto->r->st.verbose_level); - - switch (rto->r->st.verbose_level) { - case 10: - SCSC_TAG_DEBUG(WLOG, "Ring '%s' -- RING FULL DRAIN !\n", - rto->r->st.name); - scsc_wifi_get_ring_data(rto->r->st.name); - break; - case 20: - scsc_wlog_flush_ring(rto->r); - SCSC_TAG_DEBUG(WLOG, "Ring '%s' -- RING FLUSH !\n", - rto->r->st.name); - break; - case 30: - scsc_wlog_ring_set_drop_on_full(rto->r); - SCSC_TAG_DEBUG(WLOG, "Ring '%s' -- RING SET DROP ON FULL !\n", - rto->r->st.name); - break; - case 40: - if (rto->r->features_mask & WIFI_LOGGER_PACKET_FATE_SUPPORTED) { - scsc_wifilogger_ring_pktfate_start_monitoring(); - SCSC_TAG_DEBUG(WLOG, "PKTFATE MONITORING STARTED !\n"); - } - break; - case 50: - { - int i, num_rings = 10; - struct scsc_wifi_ring_buffer_status status[10]; - - scsc_wifilogger_get_rings_status(&num_rings, status); - SCSC_TAG_INFO(WLOG, "Returned rings: %d\n", num_rings); - for (i = 0; i < num_rings; i++) - SCSC_TAG_INFO(WLOG, "Retrieved ring: %s\n", status[i].name); - } - break; - default: - break; - } - - return written; -} - -const struct file_operations verbosity_fops = { - .owner = THIS_MODULE, - .open = dfs_open, - .read = dfs_verbose_read, - .write = dfs_verbose_write, - .release = dfs_release, -}; - -#endif /* CONFIG_SCSC_WIFILOGGER_TEST */ - -/*** Public ***/ - -struct scsc_ring_test_object *init_ring_test_object(struct scsc_wlog_ring *r) -{ - struct scsc_ring_test_object *rto; - - rto = kzalloc(sizeof(*rto), GFP_KERNEL); - if (!rto) - return rto; - -#ifdef CONFIG_SCSC_WIFILOGGER_TEST - rto->bsz = MAX_RECORD_SZ; - rto->rbuf = kzalloc(rto->bsz, GFP_KERNEL); - if (!rto->rbuf) { - kfree(rto); - return NULL; - } - rto->wbuf = kzalloc(rto->bsz, GFP_KERNEL); - if (!rto->wbuf) { - kfree(rto->rbuf); - kfree(rto); - return NULL; - } - /* used by on_ring_data_cb simulation test */ - INIT_LIST_HEAD(&rto->elem); - init_waitqueue_head(&rto->drain_wq); - init_waitqueue_head(&rto->rw_wq); - mutex_init(&rto->readers_lock); -#endif - rto->r = r; - - return rto; -} - -void *scsc_wlog_register_debugfs_entry(const char *ring_name, - const char *fname, - const struct file_operations *fops, - void *rto, - struct scsc_wlog_debugfs_info *di) -{ - if (!ring_name || !fname || !fops || !rto || !di) - return NULL; - - /* create root debugfs dirs if they not already exists */ - if (!di->rootdir) { - if (scsc_wlog_debugfs_global_root) { - di->rootdir = scsc_wlog_debugfs_global_root; - } else { - di->rootdir = debugfs_create_dir(SCSC_DEBUGFS_ROOT_DIRNAME, NULL); - scsc_wlog_debugfs_global_root = di->rootdir; - } - if (!di->rootdir) - goto no_rootdir; - } - - if (!di->ringdir) { - di->ringdir = debugfs_create_dir(ring_name, di->rootdir); - if (!di->ringdir) - goto no_ringdir; - } - - /* Saving ring ref @r to Inode */ - debugfs_create_file(fname, 0664, di->ringdir, rto, fops); - - return di; - -no_ringdir: -no_rootdir: - SCSC_TAG_ERR(WLOG, "Failed WiFiLogger Debugfs basic initialization\n"); - return NULL; -} - -void scsc_wifilogger_debugfs_remove_top_dir_recursive(void) -{ - if (!scsc_wlog_debugfs_global_root) - return; - - debugfs_remove_recursive(scsc_wlog_debugfs_global_root); - - SCSC_TAG_INFO(WLOG, "Wi-Fi Logger Debugfs Cleaned Up\n"); -} - -void scsc_register_common_debugfs_entries(char *ring_name, void *rto, - struct scsc_wlog_debugfs_info *di) -{ - scsc_wlog_register_debugfs_entry(ring_name, "stats", - &stats_fops, rto, di); -#ifdef CONFIG_SCSC_WIFILOGGER_TEST - scsc_wlog_register_debugfs_entry(ring_name, "verbose_level", - &verbosity_fops, rto, di); - scsc_wlog_register_debugfs_entry(ring_name, "read_record", - &read_record_fops, rto, di); - scsc_wlog_register_debugfs_entry(ring_name, "read", - &read_fops, rto, di); -#endif -} diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_debugfs.h b/drivers/misc/samsung/scsc/scsc_wifilogger_debugfs.h deleted file mode 100644 index 6689f756e025..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_debugfs.h +++ /dev/null @@ -1,67 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef _SCSC_WIFILOGGER_DEBUGFS_H_ -#define _SCSC_WIFILOGGER_DEBUGFS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "scsc_wifilogger_core.h" -#include "scsc_wifilogger.h" - -#define SCSC_DEBUGFS_ROOT "/sys/kernel/debug/wifilogger" -#define SCSC_DEBUGFS_ROOT_DIRNAME "wifilogger" - -extern struct dentry *scsc_wlog_debugfs_global_root; - -struct scsc_wlog_debugfs_info { - struct dentry *rootdir; - struct dentry *ringdir; -}; - -struct scsc_ring_test_object { - struct scsc_wlog_ring *r; -#ifdef CONFIG_SCSC_WIFILOGGER_TEST - char *rbuf; - char *wbuf; - size_t bsz; - struct list_head elem; - wait_queue_head_t drain_wq; - wait_queue_head_t rw_wq; - struct mutex readers_lock; -#endif -}; - -void *scsc_wlog_register_debugfs_entry(const char *ring_name, - const char *fname, - const struct file_operations *fops, - void *rto, - struct scsc_wlog_debugfs_info *di); - -struct scsc_ring_test_object *init_ring_test_object(struct scsc_wlog_ring *r); - -void scsc_wifilogger_debugfs_remove_top_dir_recursive(void); - -void scsc_register_common_debugfs_entries(char *ring_name, void *rto, - struct scsc_wlog_debugfs_info *di); - -int dfs_open(struct inode *ino, struct file *filp); - -int dfs_release(struct inode *ino, struct file *filp); - -#endif /* _SCSC_WIFILOGGER_DEBUGFS_H_ */ - diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_internal.c b/drivers/misc/samsung/scsc/scsc_wifilogger_internal.c deleted file mode 100644 index 0f8bd1b29aaa..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_internal.c +++ /dev/null @@ -1,232 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include - -#include "scsc_wifilogger_internal.h" - -static struct scsc_wifi_logger *wifi_logger; - -struct scsc_wifi_logger *scsc_wifilogger_get_handle(void) -{ - return wifi_logger; -} - -bool scsc_wifilogger_init(void) -{ - struct scsc_wifi_logger *wl = NULL; - - wl = kzalloc(sizeof(*wl), GFP_KERNEL); - if (!wl) { - SCSC_TAG_ERR(WLOG, - "Failed to allocate scsc_wifilogger data. Abort.\n"); - return false; - } - - mutex_init(&wl->lock); - wl->initialized = true; - wifi_logger = wl; - - return true; -} - -static int scsc_wifilogger_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - int ret = NOTIFY_DONE; - struct scsc_wifi_logger *wl = NULL; - - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, "WiFi Logger NOT initialized !\n"); - return NOTIFY_BAD; - } - - switch (event) { - case SCSC_FW_EVENT_FAILURE: - break; - case SCSC_FW_EVENT_MOREDUMP_COMPLETE: - { - char *panic_record_dump = data; - - SCSC_TAG_INFO(WLOG, "Notification received: MOREDUMP COMPLETED.\n"); - SCSC_TAG_DEBUG(WLOG, "PANIC DUMP RX\n-------------------------\n\n%s\n", - panic_record_dump); - if (wl->on_alert_cb) { - wl->on_alert_cb(panic_record_dump, - PANIC_RECORD_DUMP_BUFFER_SZ, 0, wl->on_alert_ctx); - SCSC_TAG_DEBUG(WLOG, "Alert handler -- processed %d bytes @%p\n", - PANIC_RECORD_DUMP_BUFFER_SZ, panic_record_dump); - } - ret = NOTIFY_OK; - break; - } - default: - ret = NOTIFY_BAD; - break; - } - - return ret; -} - -static struct notifier_block firmware_nb = { - .notifier_call = scsc_wifilogger_notifier, -}; - -bool scsc_wifilogger_fw_alert_init(void) -{ - struct scsc_wifi_logger *wl = NULL; - - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, "WiFi Logger NOT initialized !\n"); - return false; - } - - wl->features_mask |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED | WIFI_LOGGER_DRIVER_DUMP_SUPPORTED; - if (!mxman_register_firmware_notifier(&firmware_nb)) - wl->features_mask |= WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED; - - return true; -} - -unsigned int scsc_wifilogger_get_features(void) -{ - struct scsc_wifi_logger *wl = NULL; - - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, "WiFi Logger NOT initialized !\n"); - return 0; - } - - return wl->features_mask; -} - -bool scsc_wifilogger_get_rings_status(u32 *num_rings, - struct scsc_wifi_ring_buffer_status *status) -{ - int i, j = 0; - struct scsc_wifi_logger *wl = NULL; - - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, "WiFi Logger NOT initialized !\n"); - *num_rings = 0; - return false; - } - - for (i = 0; i < *num_rings && i < MAX_WIFI_LOGGER_RINGS; i++) - if (wl->rings[i] && wl->rings[i]->registered) - scsc_wlog_get_ring_status(wl->rings[i], &status[j++]); - *num_rings = j; - - return true; -} - -struct scsc_wlog_ring *scsc_wifilogger_get_ring_from_name(char *name) -{ - int i; - struct scsc_wlog_ring *r = NULL; - struct scsc_wifi_logger *wl = NULL; - - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "WiFi Logger NOT initialized..cannot find ring !\n"); - return r; - } - - mutex_lock(&wl->lock); - for (i = 0; i < MAX_WIFI_LOGGER_RINGS; i++) { - if (wl->rings[i] && - !strncmp(name, wl->rings[i]->st.name, RING_NAME_SZ)) { - if (wl->rings[i]->initialized && - wl->rings[i]->registered) - r = wl->rings[i]; - break; - } - } - mutex_unlock(&wl->lock); - - return r; -} - -bool scsc_wifilogger_register_ring(struct scsc_wlog_ring *r) -{ - int pos; - struct scsc_wifi_logger *wl = NULL; - - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "WiFi Logger NOT initialized..cannot register ring !\n"); - return false; - } - /** - * Calculate ring position in array from unique ring_id: - * there can be multiple distinct rings supporting the same - * feature....like pkt_fate_tx/rx - */ - pos = r->st.ring_id % MAX_WIFI_LOGGER_RINGS; - mutex_lock(&wl->lock); - if (wl->rings[pos]) { - SCSC_TAG_ERR(WLOG, - "Ring %s already registered on position %d. Abort\n", - wl->rings[pos]->st.name, pos); - mutex_unlock(&wl->lock); - return false; - } - SCSC_TAG_DEBUG(WLOG, "Registering ring %s as position %d\n", - r->st.name, pos); - wl->rings[pos] = r; - wl->features_mask |= r->features_mask; - r->wl = wl; - r->registered = true; - mutex_unlock(&wl->lock); - SCSC_TAG_INFO(WLOG, "Ring '%s' registered\n", r->st.name); - - return true; -} - -void scsc_wifilogger_destroy(void) -{ - int i; - struct scsc_wlog_ring *r = NULL; - struct scsc_wifi_logger *wl = NULL; - - wl = scsc_wifilogger_get_handle(); - if (!wl || !wl->initialized) { - SCSC_TAG_ERR(WLOG, - "WiFi Logger NOT initialized..cannot destroy!\n"); - return; - } - - mxman_unregister_firmware_notifier(&firmware_nb); - /* Remove DebufgFS hooks at first... */ - scsc_wifilogger_debugfs_remove_top_dir_recursive(); - - mutex_lock(&wl->lock); - for (i = 0; i < MAX_WIFI_LOGGER_RINGS; i++) { - if (wl->rings[i]) { - r = wl->rings[i]; - scsc_wlog_ring_change_verbosity(r, WLOG_NONE); - r->registered = false; - wl->rings[i] = NULL; - if (r->initialized) - scsc_wlog_ring_destroy(r); - } - } - wl->features_mask = 0; - mutex_unlock(&wl->lock); - kfree(wl); - wifi_logger = NULL; -} diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_internal.h b/drivers/misc/samsung/scsc/scsc_wifilogger_internal.h deleted file mode 100644 index 0aa5db90c40c..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_internal.h +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef _SCSC_WIFILOGGER_INTERNAL_H_ -#define _SCSC_WIFILOGGER_INTERNAL_H_ - -#include -#include -#include -#include -#include - -#include "scsc_wifilogger_types.h" -#include "scsc_wifilogger_core.h" -#include "scsc_wifilogger_debugfs.h" - -struct scsc_wifi_logger { - bool initialized; - struct mutex lock; - unsigned int features_mask; - struct scsc_wlog_ring *rings[MAX_WIFI_LOGGER_RINGS]; - - /** - * There is only one log_handler and alert_handler registered - * to be used across all rings: moreover just one instance of - * these handlers can exist per-ring. - */ - - /* log_handler callback registered by framework */ - void (*on_ring_buffer_data_cb)(char *ring_name, char *buffer, - int buffer_size, - struct scsc_wifi_ring_buffer_status *status, - void *ctx); - /* alert_handler callback registered by framework */ - void (*on_alert_cb)(char *buffer, int buffer_size, int err_code, void *ctx); - - void *on_ring_buffer_ctx; - void *on_alert_ctx; -}; - -bool scsc_wifilogger_init(void); -void scsc_wifilogger_destroy(void); -bool scsc_wifilogger_fw_alert_init(void); -struct scsc_wifi_logger *scsc_wifilogger_get_handle(void); -unsigned int scsc_wifilogger_get_features(void); -bool scsc_wifilogger_register_ring(struct scsc_wlog_ring *r); -struct scsc_wlog_ring *scsc_wifilogger_get_ring_from_name(char *name); -bool scsc_wifilogger_get_rings_status(u32 *num_rings, - struct scsc_wifi_ring_buffer_status *status); - -#endif /* _SCSC_WIFILOGGER_INTERNAL_H_ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_module.c b/drivers/misc/samsung/scsc/scsc_wifilogger_module.c deleted file mode 100644 index ad2f84cdafbb..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_module.c +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -/** - * Internal Reference docs for WiFi-Logger subsystem - * - * SC-507043-SW -- Android Wi-Fi Logger architecture - * SC-507780-DD -- Android Enhanced Logging - * WiFiLogger Core Driver Requirements and Design - */ -#include "scsc_wifilogger_module.h" - -static int __init scsc_wifilogger_module_init(void) -{ - if (scsc_wifilogger_init()) { - scsc_wifilogger_ring_connectivity_init(); - scsc_wifilogger_ring_wakelock_init(); - scsc_wifilogger_ring_pktfate_init(); -#ifdef CONFIG_SCSC_WIFILOGGER_TEST - scsc_wifilogger_ring_test_init(); -#endif - scsc_wifilogger_fw_alert_init(); - } else { - SCSC_TAG_ERR(WLOG, "Module init failed\n"); - return -ENOMEM; - } - - SCSC_TAG_INFO(WLOG, "Wi-Fi Logger subsystem initialized.\n"); - - return 0; -} - -static void __exit scsc_wifilogger_module_exit(void) -{ - scsc_wifilogger_destroy(); - - SCSC_TAG_INFO(WLOG, "Wi-Fi Logger subsystem unloaded.\n"); -} - -module_init(scsc_wifilogger_module_init); -module_exit(scsc_wifilogger_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Samsung SLSI"); -MODULE_DESCRIPTION("Android Wi-Fi Logger module"); diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_module.h b/drivers/misc/samsung/scsc/scsc_wifilogger_module.h deleted file mode 100644 index 4d8792755ab9..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_module.h +++ /dev/null @@ -1,27 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ - -#ifndef _SCSC_WIFILOGGER_MODULE_H_ -#define _SCSC_WIFILOGGER_MODULE_H_ - -#include -#include -#include -#include -#include -#include - -#include "scsc_wifilogger_internal.h" - -#include "scsc_wifilogger_ring_connectivity.h" -#include "scsc_wifilogger_ring_wakelock.h" -#include "scsc_wifilogger_ring_pktfate.h" - -#ifdef CONFIG_SCSC_WIFILOGGER_TEST -#include "scsc_wifilogger_ring_test.h" -#endif - -#endif /* _SCSC_WIFILOGGER_MODULE_H_ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity.c b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity.c deleted file mode 100644 index 923bf3243b40..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity.c +++ /dev/null @@ -1,121 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - *****************************************************************************/ -/* Implements */ -#include "scsc_wifilogger_ring_connectivity.h" - -/* Uses */ -#include -#include "scsc_wifilogger_ring_connectivity_api.h" -#include "scsc_wifilogger_internal.h" - -static struct scsc_wlog_ring *the_ring; - -u32 cring_lev; - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS -#include "scsc_wifilogger_debugfs.h" - -static struct scsc_wlog_debugfs_info di; - -#endif /* CONFIG_SCSC_WIFILOGGER_DEBUGFS */ - -bool scsc_wifilogger_ring_connectivity_init(void) -{ - struct scsc_wlog_ring *r = NULL; -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - struct scsc_ring_test_object *rto; -#endif - - r = scsc_wlog_ring_create(WLOGGER_RCONNECT_NAME, - RING_BUFFER_ENTRY_FLAGS_HAS_BINARY, - ENTRY_TYPE_CONNECT_EVENT, 32768 * 8, - WIFI_LOGGER_CONNECT_EVENT_SUPPORTED, - NULL, NULL, NULL); - - if (!r) { - SCSC_TAG_ERR(WLOG, "Failed to CREATE WiFiLogger ring: %s\n", - WLOGGER_RCONNECT_NAME); - return false; - } - scsc_wlog_register_verbosity_reference(r, &cring_lev); - - if (!scsc_wifilogger_register_ring(r)) { - SCSC_TAG_ERR(WLOG, "Failed to REGISTER WiFiLogger ring: %s\n", - WLOGGER_RCONNECT_NAME); - scsc_wlog_ring_destroy(r); - return false; - } - the_ring = r; - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - rto = init_ring_test_object(the_ring); - if (rto) - scsc_register_common_debugfs_entries(the_ring->st.name, rto, &di); -#endif - - return true; -} - -/**** Producer API ******/ - -int scsc_wifilogger_ring_connectivity_fw_event(wlog_verbose_level lev, u16 fw_event_id, - u64 fw_timestamp, void *fw_bulk_data, size_t fw_blen) -{ - struct scsc_wifi_ring_buffer_driver_connectivity_event event_item; - - if (!the_ring) - return 0; - - SCSC_TAG_DEBUG(WLOG, "EL -- RX MLME_EVENT_LOG_INFO - event_id[%d] @0x%x\n", - fw_event_id, fw_timestamp); - event_item.event = fw_event_id; - - return scsc_wlog_write_record(the_ring, fw_bulk_data, fw_blen, &event_item, - sizeof(event_item), lev, fw_timestamp); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_connectivity_fw_event); - -int scsc_wifilogger_ring_connectivity_driver_event(wlog_verbose_level lev, - u16 driver_event_id, unsigned int tag_count, ...) -{ - int i; - u64 timestamp; - va_list ap; - u8 tlvs[MAX_TLVS_SZ]; - size_t tlvs_sz = 0; - struct scsc_tlv_log *tlv = NULL; - struct scsc_wifi_ring_buffer_driver_connectivity_event event_item; - - if (!the_ring) - return 0; - - timestamp = local_clock(); - - SCSC_TAG_DEBUG(WLOG, "EL -- RX Driver CONNECTIVITY EVENT - event_id[%d] @0x%x\n", - driver_event_id, timestamp); - - event_item.event = driver_event_id; - va_start(ap, tag_count); - for (i = 0; i < tag_count && - tlvs_sz + sizeof(*tlv) < MAX_TLVS_SZ; i++) { - tlv = (struct scsc_tlv_log *)(tlvs + tlvs_sz); - tlv->tag = (u16)va_arg(ap, int); - tlv->length = (u16)va_arg(ap, int); - if (tlvs_sz + sizeof(*tlv) + tlv->length >= MAX_TLVS_SZ) { - WARN(true, - "TLVs container too small [%d]....truncating event's tags !\n", - MAX_TLVS_SZ); - break; - } - memcpy(&tlv->value, va_arg(ap, u8 *), tlv->length); - tlvs_sz += sizeof(*tlv) + tlv->length; - } - va_end(ap); - - return scsc_wlog_write_record(the_ring, tlvs, tlvs_sz, &event_item, - sizeof(event_item), lev, timestamp); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_connectivity_driver_event); diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity.h b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity.h deleted file mode 100644 index 06c3106ff39e..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity.h +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RING_CONNECTIVITY_H__ -#define __SCSC_WIFILOGGER_RING_CONNECTIVITY_H__ - -#include -#include -#include -#include -#include - -#include "scsc_wifilogger_core.h" -#include "scsc_wifilogger.h" - -#define MAX_TLVS_SZ 1024 -#define WLOGGER_RCONNECT_NAME "connectivity" - -/** - * A local mirror for this ring's current verbose level: - * avoids func-call and minimizes impact when ring is disabled - */ -extern u32 cring_lev; - -bool scsc_wifilogger_ring_connectivity_init(void); - -int scsc_wifilogger_ring_connectivity_driver_event(wlog_verbose_level lev, - u16 driver_event_id, unsigned int tag_count, ...); - -int scsc_wifilogger_ring_connectivity_fw_event(wlog_verbose_level lev, u16 fw_event_id, - u64 fw_timestamp, void *fw_bulk_data, size_t fw_blen); - -#endif /* __SCSC_WIFILOGGER_RING_CONNECTIVITY_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity_api.h b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity_api.h deleted file mode 100644 index ca038ad3dd8f..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_connectivity_api.h +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RING_CONNECTIVITY_API_H__ -#define __SCSC_WIFILOGGER_RING_CONNECTIVITY_API_H__ -/** Android Enhanced Logging - * - * CONNECTIVITY RING -- Public Producer API - * - * This ring collects a number of events originated by FW and Driver; given the different - * format of the provided payload between FW and Driver the API is splitted in two classes: - * once to be invoked on fw events and the other on driver events. - */ - -#ifdef CONFIG_SCSC_WIFILOGGER - -#include "scsc_wifilogger_ring_connectivity.h" -/** - * DRIVER-Produced Connectivity Events - * - * @lev: chosen verbosity level - * @driver_event_id: id of the event reported by the driver - * @tag_count: number of TLV-TRIPLETS constituting the variadic portion of the call. - * Provided TLV triplets are composed as follows: - * - Types(Tag) are defined in scsc_wifilogger_types.h - * - Length in bytes of value - * - Value is a POINTER to the area holding the Length bytes to copy - * - * This function will take care to build the needed inner record-header and push the - * log material to the related ring, adding also a proper driver-built timestamp. - * - * An example invokation on Association Request received at driver: - * - * SCSC_WLOG_DRIVER_EVENT(WLOG_NORMAL, WIFI_EVENT_ASSOCIATION_REQUESTED, 3, - * WIFI_TAG_BSSID, ETH_ALEN, sme->bssid, - * WIFI_TAG_SSID, sme->ssid_len, sme->ssid, - * WIFI_TAG_CHANNEL, sizeof(u16), &sme->channel->center_freq); - * - * BE AWARE THAT tag_count parameeters expects the NUMBER of TRIPLETS - * NOT the number of variadic params. - */ -#define SCSC_WLOG_DRIVER_EVENT(lev, driver_event_id, tag_count, tag_args...) \ - do { \ - if (cring_lev && (lev) <= cring_lev) \ - scsc_wifilogger_ring_connectivity_driver_event((lev), (driver_event_id), \ - (tag_count), tag_args); \ - } while (0) - -/** - * FW-Produced Connectivity Events - * - * @lev: chosen verbosity level - * @fw_event_id: id of the event as provided in the field - * MLME-EVENT-LOG.indication[Event] - * @fw_timestamp: timestamp of the event as provided in the field - * MLME-EVENT-LOG.indication[TSF Time] - * @fw_bulk_data: the bulk data contained in the MLME signal. - * "The bulk data shall contain TLV encoded parameters for that event" - * @fw_blen: the length of the above bulk_data - * - * This function will take care to build the needed inner record-header and push the - * log material to the related ring. - */ -#define SCSC_WLOG_FW_EVENT(lev, fw_event_id, fw_timestamp, fw_bulk_data, fw_blen) \ - do { \ - if (cring_lev && (lev) <= cring_lev) \ - scsc_wifilogger_ring_connectivity_fw_event((lev), (fw_event_id), (fw_timestamp), \ - (fw_bulk_data), (fw_blen)); \ - } while (0) -#else - -#define SCSC_WLOG_DRIVER_EVENT(lev, driver_event_id, tag_count, tag_args...) do {} while (0) -#define SCSC_WLOG_FW_EVENT(lev, fw_event_id, fw_timestamp, fw_bulk_data, fw_blen) do {} while (0) - -#endif /* CONFIG_SCSC_WIFILOGGER */ - -#endif /* __SCSC_WIFILOGGER_RING_CONNECTIVITY_API_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate.c b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate.c deleted file mode 100644 index a133d39c62db..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate.c +++ /dev/null @@ -1,284 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - *****************************************************************************/ -/* Implements */ -#include "scsc_wifilogger_ring_pktfate.h" - -/* Uses */ -#include -#include "scsc_wifilogger_internal.h" - -static bool pktfate_monitor_started; - -static wifi_tx_report txr; -static wifi_rx_report rxr; -static struct scsc_wlog_ring *fate_ring_tx; -static struct scsc_wlog_ring *fate_ring_rx; - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS -#include "scsc_wifilogger_debugfs.h" -#include "scsc_wifilogger.h" - -static struct scsc_wlog_debugfs_info di_tx, di_rx; - -#ifdef CONFIG_SCSC_WIFILOGGER_TEST -static ssize_t dfs_read_fates(struct file *filp, char __user *ubuf, - size_t count, loff_t *f_pos) -{ - size_t got_sz, n_provided_fates = 0, n_requested_fates; - struct scsc_ring_test_object *rto; - wifi_tx_report *tx_report_bufs = NULL; - wifi_rx_report *rx_report_bufs = NULL; - void *srcbuf = NULL; - - if (!filp->private_data) - return -EINVAL; - rto = filp->private_data; - - if (!strncmp(rto->r->st.name, WLOGGER_RFATE_TX_NAME, RING_NAME_SZ - 1)) { - n_requested_fates = count / sizeof(wifi_tx_report); - tx_report_bufs = vmalloc(sizeof(wifi_tx_report) * n_requested_fates); - if (tx_report_bufs) - scsc_wifi_get_tx_pkt_fates(tx_report_bufs, n_requested_fates, - &n_provided_fates); - got_sz = sizeof(wifi_tx_report) * n_provided_fates; - srcbuf = tx_report_bufs; - } else { - n_requested_fates = count / sizeof(wifi_rx_report); - rx_report_bufs = vmalloc(sizeof(wifi_rx_report) * n_requested_fates); - if (rx_report_bufs) - scsc_wifi_get_rx_pkt_fates(rx_report_bufs, n_requested_fates, - &n_provided_fates); - got_sz = sizeof(wifi_rx_report) * n_provided_fates; - srcbuf = rx_report_bufs; - } - SCSC_TAG_DEBUG(WLOG, "Ring '%s'...asked for %d fates....GOT %d\n", - rto->r->st.name, n_requested_fates, n_provided_fates); - if (copy_to_user(ubuf, srcbuf, got_sz)) - return -EFAULT; - *f_pos += got_sz; - - return got_sz; -} - -const struct file_operations get_fates_fops = { - .owner = THIS_MODULE, - .open = dfs_open, - .read = dfs_read_fates, - .release = dfs_release, -}; -#endif /* CONFIG_SCSC_WIFILOGGER_TEST */ - -#endif /* CONFIG_SCSC_WIFILOGGER_DEBUGFS */ - -bool is_pktfate_monitor_started(void) -{ - return pktfate_monitor_started; -} - -bool scsc_wifilogger_ring_pktfate_init(void) -{ - struct scsc_wlog_ring *r = NULL; -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - struct scsc_ring_test_object *rto_tx, *rto_rx; -#endif - - r = scsc_wlog_ring_create(WLOGGER_RFATE_TX_NAME, - RING_BUFFER_ENTRY_FLAGS_HAS_BINARY, - ENTRY_TYPE_PKT, 32768 * 4, - WIFI_LOGGER_PACKET_FATE_SUPPORTED, - NULL, NULL, NULL); - if (!r) { - SCSC_TAG_ERR(WLOG, "Failed to CREATE WiFiLogger ring: %s\n", - WLOGGER_RFATE_TX_NAME); - return false; - } - fate_ring_tx = r; - - r = scsc_wlog_ring_create(WLOGGER_RFATE_RX_NAME, - RING_BUFFER_ENTRY_FLAGS_HAS_BINARY, - ENTRY_TYPE_PKT, 32768 * 4, - WIFI_LOGGER_PACKET_FATE_SUPPORTED, - NULL, NULL, NULL); - if (!r) { - SCSC_TAG_ERR(WLOG, "Failed to CREATE WiFiLogger ring: %s\n", - WLOGGER_RFATE_RX_NAME); - scsc_wlog_ring_destroy(fate_ring_tx); - return false; - } - fate_ring_rx = r; - - if (!scsc_wifilogger_register_ring(fate_ring_tx)) { - SCSC_TAG_ERR(WLOG, "Failed to REGISTER WiFiLogger ring: %s\n", - fate_ring_tx->st.name); - scsc_wlog_ring_destroy(fate_ring_tx); - scsc_wlog_ring_destroy(fate_ring_rx); - return false; - } - if (!scsc_wifilogger_register_ring(fate_ring_rx)) { - SCSC_TAG_ERR(WLOG, "Failed to REGISTER WiFiLogger ring: %s\n", - fate_ring_rx->st.name); - scsc_wlog_ring_destroy(fate_ring_tx); - scsc_wlog_ring_destroy(fate_ring_rx); - return false; - } - - // Just in case framework invokes with min_data_size != 0 - scsc_wlog_ring_set_drop_on_full(fate_ring_tx); - scsc_wlog_ring_set_drop_on_full(fate_ring_rx); - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - /* The test object is shared between all the debugfs entries - * belonging to the same ring. - */ - rto_tx = init_ring_test_object(fate_ring_tx); - if (rto_tx) { - scsc_register_common_debugfs_entries(fate_ring_tx->st.name, rto_tx, &di_tx); -#ifdef CONFIG_SCSC_WIFILOGGER_TEST - scsc_wlog_register_debugfs_entry(fate_ring_tx->st.name, "get_fates", - &get_fates_fops, rto_tx, &di_tx); -#endif - } - - rto_rx = init_ring_test_object(fate_ring_rx); - if (rto_rx) { - scsc_register_common_debugfs_entries(fate_ring_rx->st.name, rto_rx, &di_rx); -#ifdef CONFIG_SCSC_WIFILOGGER_TEST - scsc_wlog_register_debugfs_entry(fate_ring_rx->st.name, "get_fates", - &get_fates_fops, rto_rx, &di_rx); -#endif - } -#endif - - return true; -} - -void scsc_wifilogger_ring_pktfate_start_monitoring(void) -{ - if (!fate_ring_rx || !fate_ring_tx) - return; - - /* Just in case */ - scsc_wlog_flush_ring(fate_ring_tx); - scsc_wlog_start_logging(fate_ring_tx, WLOG_DEBUG, 0, 0, 0); - scsc_wlog_flush_ring(fate_ring_rx); - scsc_wlog_start_logging(fate_ring_rx, WLOG_DEBUG, 0, 0, 0); - pktfate_monitor_started = true; - - SCSC_TAG_INFO(WLOG, "PacketFate monitor started.\n"); -} - -/**** Producer API ******/ -void scsc_wifilogger_ring_pktfate_new_assoc(void) -{ - SCSC_TAG_INFO(WLOG, "New Association started...flushing PacketFate rings.\n"); - scsc_wlog_flush_ring(fate_ring_tx); - scsc_wlog_flush_ring(fate_ring_rx); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_pktfate_new_assoc); - -void scsc_wifilogger_ring_pktfate_get_fates(int fate, void *report_bufs, - size_t n_requested_fates, - size_t *n_provided_fates) -{ - struct scsc_wlog_ring *r; - u32 n_req_fates = (u32)n_requested_fates; - size_t blen; - - r = (fate == TX_FATE) ? fate_ring_tx : fate_ring_rx; - if (fate == TX_FATE) - blen = sizeof(wifi_tx_report) * n_req_fates; - else - blen = sizeof(wifi_rx_report) * n_req_fates; - scsc_wlog_read_max_records(r, report_bufs, blen, &n_req_fates); - *n_provided_fates = n_req_fates; - - SCSC_TAG_INFO(WLOG, "[%s]:: GET %s pkt_fates -- Requested:%zd - Got:%zd\n", - r->st.name, - (fate == TX_FATE) ? "TX" : "RX", n_requested_fates, *n_provided_fates); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_pktfate_get_fates); - -/** - * Here we're Just saving the egressing ETH frame for now with the - * provided initial fate (which is fixed to TX_PKT_FATE_DRV_QUEUED). - * In a full pktfate implementation as required by WiFi-Logger we - * should track down this eth frame using the host_tag and then - * account for the final fate of the frame looking at Debugging - * Information Element provided in subsequent UnidataTx.confirm, BUT - * such confirm as of now does NOT provide any Debugging Element NOR - * any additional interesting information related to the packet fates - * defined. - */ -void scsc_wifilogger_ring_pktfate_log_tx_frame(wifi_tx_packet_fate fate, - u16 htag, void *frame, - size_t len, bool ma_unitdata) -{ - if (len > MAX_FRAME_LEN_ETHERNET) { - SCSC_TAG_WARNING(WLOG, "pktfate TX:: dropped unplausible length frame.\n"); - return; - } - - if (ma_unitdata) - len = len <= MAX_UNITDATA_LOGGED_SZ ? len : MAX_UNITDATA_LOGGED_SZ; - - txr.fate = fate; - txr.frame_inf.payload_type = FRAME_TYPE_ETHERNET_II; - txr.frame_inf.frame_len = len; - txr.frame_inf.driver_timestamp_usec = ktime_to_ns(ktime_get_boottime()); - txr.frame_inf.firmware_timestamp_usec = 0; - memcpy(&txr.frame_inf.frame_content, frame, len); - //TODO MD5 checksum using Kernel Crypto API - memset(&txr.md5_prefix, 0x00, MD5_PREFIX_LEN); - /** - * We have to waste a lot of space storing the frame in a full-sized - * frame_content array, even if the frame size is much smaller, because - * the wifi-logger API (get_tx/rx_pkt_fates) reports multiple of struct - * wifi_tx/rx_packet_fates and does NOT return the effectively read bytes. - * The real size (that we cannot use) being: - * - * real_txr_sz = sizeof(txr) - sizeof(txr.frame_inf.frame_content) + len; - * - * frame_len field is anyway provided to recognize the actual end of frame. - */ - scsc_wlog_write_record(fate_ring_tx, NULL, 0, &txr, sizeof(txr), WLOG_DEBUG, 0); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_pktfate_log_tx_frame); - -void scsc_wifilogger_ring_pktfate_log_rx_frame(wifi_rx_packet_fate fate, u16 du_desc, - void *frame, size_t len, bool ma_unitdata) -{ - if ((du_desc == SCSC_DUD_ETHERNET_FRAME && len > MAX_FRAME_LEN_ETHERNET) || - (du_desc == SCSC_DUD_80211_FRAME && len > MAX_FRAME_LEN_80211_MGMT)) { - SCSC_TAG_WARNING(WLOG, "pktfate RX:: dropped unplausible length frame.\n"); - return; - } - - if (ma_unitdata) - len = len <= MAX_UNITDATA_LOGGED_SZ ? len : MAX_UNITDATA_LOGGED_SZ; - - rxr.fate = fate; - rxr.frame_inf.payload_type = du_desc == SCSC_DUD_ETHERNET_FRAME ? FRAME_TYPE_ETHERNET_II : - (du_desc == SCSC_DUD_80211_FRAME ? FRAME_TYPE_80211_MGMT : FRAME_TYPE_UNKNOWN); - rxr.frame_inf.frame_len = len; - rxr.frame_inf.driver_timestamp_usec = ktime_to_ns(ktime_get_boottime()); - rxr.frame_inf.firmware_timestamp_usec = 0; - memcpy(&rxr.frame_inf.frame_content, frame, len); - //TODO MD5 checksum using Kernel Crypto API - memset(&rxr.md5_prefix, 0x00, MD5_PREFIX_LEN); - /** - * We have to waste a lot of space storing the frame in a full-sized - * frame_content array, even if the frame size is much smaller, because - * the wifi-logger API (get_tx/rx_pkt_fates) reports multiple of struct - * wifi_tx/rx_packet_fates and does NOT return the effectively read bytes. - * The real size (that we cannot use) being: - * - * real_txr_sz = sizeof(txr) - sizeof(txr.frame_inf.frame_content) + len; - * - * frame_len field is anyway provided to recognize the actual end of frame. - */ - scsc_wlog_write_record(fate_ring_rx, NULL, 0, &rxr, sizeof(rxr), WLOG_DEBUG, 0); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_pktfate_log_rx_frame); diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate.h b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate.h deleted file mode 100644 index dfea593d6b5a..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate.h +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RING_PKTFATE_H__ -#define __SCSC_WIFILOGGER_RING_PKTFATE_H__ - -#include -#include -#include -#include -#include - -#include "scsc_wifilogger_core.h" -#include "scsc_wifilogger.h" - -#define TX_FATE 0 -#define RX_FATE 1 -#define WLOGGER_RFATE_TX_NAME "pkt_fate_tx" -#define WLOGGER_RFATE_RX_NAME "pkt_fate_rx" -#define MAX_UNITDATA_LOGGED_SZ 100 - -#define SCSC_DUD_ETHERNET_FRAME 0 -#define SCSC_DUD_80211_FRAME 1 -#define SCSC_DUD_MLME 2 - -bool is_pktfate_monitor_started(void); -bool scsc_wifilogger_ring_pktfate_init(void); -void scsc_wifilogger_ring_pktfate_start_monitoring(void); -void scsc_wifilogger_ring_pktfate_new_assoc(void); -void scsc_wifilogger_ring_pktfate_log_tx_frame(wifi_tx_packet_fate fate, - u16 htag, void *pkt, - size_t len, bool ma_unitdata); -void scsc_wifilogger_ring_pktfate_log_rx_frame(wifi_rx_packet_fate fate, u16 du_desc, - void *frame, size_t len, bool ma_unitdata); -void scsc_wifilogger_ring_pktfate_get_fates(int fate, void *report_bufs, - size_t n_requested_fates, - size_t *n_provided_fates); -#endif /* __SCSC_WIFILOGGER_RING_PKTFATE_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate_api.h b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate_api.h deleted file mode 100644 index dcfe4911b581..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_pktfate_api.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RING_PKTFATE_API_H__ -#define __SCSC_WIFILOGGER_RING_PKTFATE_API_H__ - -/** Android Enhanced Logging - * - * PKTFATE RING -- Public Producer API - * - */ - -#ifdef CONFIG_SCSC_WIFILOGGER -#include "scsc_wifilogger_ring_pktfate.h" - -#define SCSC_WLOG_PKTFATE_NEW_ASSOC() \ - do { \ - if (is_pktfate_monitor_started()) \ - scsc_wifilogger_ring_pktfate_new_assoc(); \ - } while (0) - -#define SCSC_WLOG_PKTFATE_LOG_TX_DATA_FRAME(htag, frame, flen) \ - do { \ - if (is_pktfate_monitor_started()) \ - scsc_wifilogger_ring_pktfate_log_tx_frame(TX_PKT_FATE_DRV_QUEUED, (htag), \ - (void *)(frame), (flen), true); \ - } while (0) - -#define SCSC_WLOG_PKTFATE_LOG_RX_DATA_FRAME(du_desc, frame, flen) \ - do { \ - if (is_pktfate_monitor_started() && \ - ((du_desc) == SCSC_DUD_ETHERNET_FRAME || (du_desc) == SCSC_DUD_80211_FRAME)) \ - scsc_wifilogger_ring_pktfate_log_rx_frame(RX_PKT_FATE_DRV_QUEUED, (du_desc), \ - (void *)(frame), (flen), true); \ - } while (0) - -#define SCSC_WLOG_PKTFATE_LOG_TX_CTRL_FRAME(htag, frame, flen) \ - do { \ - if (is_pktfate_monitor_started()) \ - scsc_wifilogger_ring_pktfate_log_tx_frame(TX_PKT_FATE_DRV_QUEUED, (htag), \ - (void *)(frame), (flen), false); \ - } while (0) - -#define SCSC_WLOG_PKTFATE_LOG_RX_CTRL_FRAME(frame, flen) \ - do { \ - if (is_pktfate_monitor_started()) \ - scsc_wifilogger_ring_pktfate_log_rx_frame(RX_PKT_FATE_DRV_QUEUED, SCSC_DUD_MLME, \ - (void *)(frame), (flen), false); \ - } while (0) - -#else - -#define SCSC_WLOG_PKTFATE_NEW_ASSOC() do {} while (0) -#define SCSC_WLOG_PKTFATE_LOG_TX_DATA_FRAME(htag, skb_mac, skb_hlen) do {} while (0) -#define SCSC_WLOG_PKTFATE_LOG_TX_CTRL_FRAME(htag, skb_mac, skb_hlen) do {} while (0) -#define SCSC_WLOG_PKTFATE_LOG_RX_DATA_FRAME(du_desc, skb_mac, skb_hlen) do {} while (0) -#define SCSC_WLOG_PKTFATE_LOG_RX_CTRL_FRAME(frame, flen) do {} while (0) - -#endif /* CONFIG_SCSC_WIFILOGGER */ - -#endif /* __SCSC_WIFILOGGER_RING_PKTFATE_API_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_test.c b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_test.c deleted file mode 100644 index 818b16de7510..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_test.c +++ /dev/null @@ -1,135 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - *****************************************************************************/ -/* Implements */ -#include "scsc_wifilogger_ring_test.h" - -/* Uses */ -#include "scsc_wifilogger_internal.h" - -static u32 seq; -static struct scsc_wlog_ring *the_ring; - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS -#include "scsc_wifilogger_debugfs.h" - -static struct scsc_wlog_debugfs_info di; -#endif /* CONFIG_SCSC_WIFILOGGER_DEBUGFS */ - -static int ring_test_loglevel_change_cb(struct scsc_wlog_ring *r, - u32 new_loglevel) -{ - SCSC_TAG_DEBUG(WLOG, - "==>> TEST RING SETTING CUSTOM LogLevel for ring: %s -- to:%d\n", - r->st.name, new_loglevel); - - return 0; -} - -bool ring_test_custom_init(struct scsc_wlog_ring *r) -{ - SCSC_TAG_DEBUG(WLOG, "Custom init for ring:%s\n", r->st.name); - - return true; -} - -bool ring_test_custom_fini(struct scsc_wlog_ring *r) -{ - SCSC_TAG_DEBUG(WLOG, "Custom fini for ring:%s\n", r->st.name); - - return true; -} - -/* Producer API */ -int scsc_wifilogger_ring_test_write(char *buf, size_t blen) -{ - struct tring_hdr thdr; - - if (!the_ring) - return 0; - - thdr.seq = seq++; - thdr.fake = 666 & seq; - - return scsc_wlog_write_record(the_ring, buf, blen, &thdr, sizeof(thdr), WLOG_NORMAL, 0); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_test_write); - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS -static ssize_t dfs_record_write(struct file *filp, const char __user *ubuf, - size_t count, loff_t *f_pos) -{ - ssize_t written; - struct scsc_ring_test_object *rto; - - if (!filp->private_data) - return -EINVAL; - rto = filp->private_data; - - count = count < rto->bsz ? count : rto->bsz; - if (copy_from_user(rto->wbuf, ubuf, count)) - return -EINVAL; - written = scsc_wifilogger_ring_test_write(rto->wbuf, count); - if (!written && count) - return -EAGAIN; - wake_up_interruptible(&rto->rw_wq); - *f_pos += written; - - return written; -} - -const struct file_operations write_record_fops = { - .owner = THIS_MODULE, - .open = dfs_open, - .write = dfs_record_write, - .release = dfs_release, -}; -#endif - -bool scsc_wifilogger_ring_test_init(void) -{ - struct scsc_wlog_ring *r = NULL; -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - struct scsc_ring_test_object *rto; -#endif - - r = scsc_wlog_ring_create(WLOGGER_RTEST_NAME, - RING_BUFFER_ENTRY_FLAGS_HAS_BINARY, - ENTRY_TYPE_DATA, 32768, - WIFI_LOGGER_SCSC_TEST_RING_SUPPORTED, - ring_test_custom_init, ring_test_custom_fini, - NULL); - - if (!r) { - SCSC_TAG_ERR(WLOG, "Failed to CREATE WiFiLogger ring: %s\n", - WLOGGER_RTEST_NAME); - return false; - } - /* Registering custom loglevel change callback */ - scsc_wlog_register_loglevel_change_cb(r, ring_test_loglevel_change_cb); - - if (!scsc_wifilogger_register_ring(r)) { - SCSC_TAG_ERR(WLOG, "Failed to REGISTER WiFiLogger ring: %s\n", - WLOGGER_RTEST_NAME); - scsc_wlog_ring_destroy(r); - return false; - } - the_ring = r; - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - /* This test object is shared between all the debugfs entries - * belonging to this ring. - */ - rto = init_ring_test_object(the_ring); - if (rto) { - scsc_register_common_debugfs_entries(the_ring->st.name, rto, &di); - /* A write is specific to the ring...*/ - scsc_wlog_register_debugfs_entry(the_ring->st.name, "write_record", - &write_record_fops, rto, &di); - } -#endif - - return true; -} diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_test.h b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_test.h deleted file mode 100644 index 2020d846e28e..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_test.h +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RING_TEST_H__ -#define __SCSC_WIFILOGGER_RING_TEST_H__ - -#include -#include -#include -#include -#include - -#include "scsc_wifilogger_core.h" -#include "scsc_wifilogger.h" - -#define WLOGGER_RTEST_NAME "test" - -struct tring_hdr { - u32 seq; - u64 fake; -} __packed; - -bool scsc_wifilogger_ring_test_init(void); - -int scsc_wifilogger_ring_test_write(char *buf, size_t blen); -#endif /* __SCSC_WIFILOGGER_RING_TEST_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock.c b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock.c deleted file mode 100644 index 919314f19408..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock.c +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - *****************************************************************************/ -/* Implements */ -#include "scsc_wifilogger_ring_wakelock.h" - -/* Uses */ -#include "scsc_wifilogger_ring_wakelock_api.h" -#include "scsc_wifilogger_internal.h" - -static struct scsc_wlog_ring *the_ring; -u32 wring_lev; - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS -#include "scsc_wifilogger_debugfs.h" - -static struct scsc_wlog_debugfs_info di; - -#endif /* CONFIG_SCSC_WIFILOGGER_DEBUGFS */ - -bool scsc_wifilogger_ring_wakelock_init(void) -{ - struct scsc_wlog_ring *r = NULL; -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - struct scsc_ring_test_object *rto = NULL; -#endif - - r = scsc_wlog_ring_create(WLOGGER_RWAKELOCK_NAME, - RING_BUFFER_ENTRY_FLAGS_HAS_BINARY, - ENTRY_TYPE_WAKE_LOCK, 65536, - WIFI_LOGGER_WAKE_LOCK_SUPPORTED, - NULL, NULL, NULL); - - if (!r) { - SCSC_TAG_ERR(WLOG, "Failed to CREATE WiFiLogger ring: %s\n", - WLOGGER_RWAKELOCK_NAME); - return false; - } - scsc_wlog_register_verbosity_reference(r, &wring_lev); - - if (!scsc_wifilogger_register_ring(r)) { - SCSC_TAG_ERR(WLOG, "Failed to REGISTER WiFiLogger ring: %s\n", - WLOGGER_RWAKELOCK_NAME); - scsc_wlog_ring_destroy(r); - return false; - } - the_ring = r; - -#ifdef CONFIG_SCSC_WIFILOGGER_DEBUGFS - rto = init_ring_test_object(the_ring); - if (rto) - scsc_register_common_debugfs_entries(the_ring->st.name, rto, &di); -#endif - - return true; -} - -/**** Producer API ******/ - -int scsc_wifilogger_ring_wakelock_action(u32 verbose_level, int status, - char *wl_name, int reason) -{ - u64 timestamp; - struct scsc_wake_lock_event wl_event; - - if (!the_ring) - return 0; - - timestamp = local_clock(); - SCSC_TAG_DBG4(WLOG, "EL -- WAKELOCK[%s] - status:%d reason:%d @0x%x\n", - wl_name, status, reason, timestamp); - - wl_event.status = status; - wl_event.reason = reason; - return scsc_wlog_write_record(the_ring, wl_name, strlen(wl_name), &wl_event, - sizeof(wl_event), verbose_level, timestamp); -} -EXPORT_SYMBOL(scsc_wifilogger_ring_wakelock_action); - diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock.h b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock.h deleted file mode 100644 index fef9a87c0179..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RING_WAKELOCK_H__ -#define __SCSC_WIFILOGGER_RING_WAKELOCK_H__ - -#include -#include - -#include "scsc_wifilogger_core.h" -#include "scsc_wifilogger.h" - -#define WLOGGER_RWAKELOCK_NAME "wakelock" - -extern u32 wring_lev; - -int scsc_wifilogger_ring_wakelock_action(u32 verbose_level, int status, - char *wl_name, int reason); - - -bool scsc_wifilogger_ring_wakelock_init(void); -#endif /* __SCSC_WIFILOGGER_RING_WAKELOCK_H__ */ - diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock_api.h b/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock_api.h deleted file mode 100644 index d4b38ea63e01..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_ring_wakelock_api.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RING_WAKELOCK_API_H__ -#define __SCSC_WIFILOGGER_RING_WAKELOCK_API_H__ - -/** - * Android Enhanced Logging - * - * WAKELOCK EVENTS RING -- Public Producer API - * - */ -enum { - WL_TAKEN = 0, - WL_RELEASED -}; - -enum { - WL_REASON_TX = 0, - WL_REASON_RX, - WL_REASON_ROAM -}; - -#ifdef CONFIG_SCSC_WIFILOGGER - -#include "scsc_wifilogger_ring_wakelock.h" - -#define SCSC_WLOG_WAKELOCK(lev, status, wl_name, reason) \ - do { \ - if (wring_lev && (lev) <= wring_lev) \ - scsc_wifilogger_ring_wakelock_action((lev), (status), (wl_name), (reason)); \ - } while (0) - -#else - -#define SCSC_WLOG_WAKELOCK(lev, status, wl_name, reason) do {} while (0) - -#endif - -#endif /* __SCSC_WIFILOGGER_RING_WAKELOCK_API_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_rings.h b/drivers/misc/samsung/scsc/scsc_wifilogger_rings.h deleted file mode 100644 index c3792a5e9abb..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_rings.h +++ /dev/null @@ -1,15 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef __SCSC_WIFILOGGER_RINGS_H__ -#define __SCSC_WIFILOGGER_RINGS_H__ - -#include "scsc_wifilogger_types.h" -/* This file groups and exports all rings Producer APIs */ -#include "scsc_wifilogger_ring_connectivity_api.h" -#include "scsc_wifilogger_ring_wakelock_api.h" -#include "scsc_wifilogger_ring_pktfate_api.h" - -#endif /* __SCSC_WIFILOGGER_RINGS_H__ */ diff --git a/drivers/misc/samsung/scsc/scsc_wifilogger_types.h b/drivers/misc/samsung/scsc/scsc_wifilogger_types.h deleted file mode 100755 index 20142a052b78..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wifilogger_types.h +++ /dev/null @@ -1,435 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - ******************************************************************************/ -#ifndef _SCSC_WIFILOGGER_TYPES_H_ -#define _SCSC_WIFILOGGER_TYPES_H_ -/** - * These types are derived from definitions in: - * - * hardware/libhardware_legacy/include/hardware_legacy/wifi_logger.h - * hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h - * - * Descriptive comments are in wifi_logger.h original file. - * Here we avoided using typedef that are in contrast with Kernel - * coding style though. - */ -#include - -#define LOGGER_MAJOR_VERSION 1 -#define LOGGER_MINOR_VERSION 0 -#define LOGGER_MICRO_VERSION 0 - -/** - * Be aware that there can be multiple distinct rings, registered - * with different names but supporting the same feature: an example - * being pkt_fate_tx and pkt_fate_rx. Rings are registered by ring_id. - */ -#ifndef CONFIG_SCSC_WIFILOGGER_TEST_RING -#define MAX_WIFI_LOGGER_RINGS 10 -#else -#define MAX_WIFI_LOGGER_RINGS 11 -#endif - -typedef enum { - WIFI_SUCCESS = 0, - WIFI_ERROR_NONE = 0, - WIFI_ERROR_UNKNOWN = -1, - WIFI_ERROR_UNINITIALIZED = -2, - WIFI_ERROR_NOT_SUPPORTED = -3, - WIFI_ERROR_NOT_AVAILABLE = -4, /* Not available right now, but try later */ - WIFI_ERROR_INVALID_ARGS = -5, - WIFI_ERROR_INVALID_REQUEST_ID = -6, - WIFI_ERROR_TIMED_OUT = -7, - WIFI_ERROR_TOO_MANY_REQUESTS = -8, /* Too many instances of this request */ - WIFI_ERROR_OUT_OF_MEMORY = -9, - WIFI_ERROR_BUSY = -10, -} wifi_error; - -/* Verbosity */ -typedef enum { - WLOG_NONE = 0, - WLOG_NORMAL = 1, - WLOG_LAZY = 2, - WLOG_DEBUG = 3, -} wlog_verbose_level; - -/* Feature set */ -enum { - WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), - WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), - WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), - WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), - WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), - WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), - WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), - WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), - WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), -#ifdef CONFIG_SCSC_WIFILOGGER_TEST - WIFI_LOGGER_SCSC_TEST_RING_SUPPORTED = (1 << (9)), -#endif -}; - -enum { - RING_BUFFER_ENTRY_FLAGS_HAS_BINARY = (1 << (0)), - RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1)) -}; - -#define RING_NAME_SZ 32 - -struct scsc_wifi_ring_buffer_status { - u8 name[RING_NAME_SZ]; - u32 flags; - int ring_id; /* unique integer representing the ring */ - u32 rb_byte_size; /* total memory size allocated for the buffer */ - u32 verbose_level; /* verbose level for ring buffer */ - u32 written_bytes; /* number of bytes that was written to the - * buffer by driver, monotonously increasing - * integer - */ - u32 read_bytes; /* number of bytes that was read from the buffer - * by user land, monotonously increasing integer - */ - u32 written_records; /* number of records that was written to the - * buffer by driver, monotonously increasing - * integer - */ -}; - -typedef void (*on_ring_buffer_data)(char *ring_name, char *buffer, int buffer_size, - struct scsc_wifi_ring_buffer_status *status, void *ctx); -typedef void (*on_alert)(char *buffer, int buffer_size, int err_code, void *ctx); - -enum { - ENTRY_TYPE_CONNECT_EVENT = 1, - ENTRY_TYPE_PKT, - ENTRY_TYPE_WAKE_LOCK, - ENTRY_TYPE_POWER_EVENT, - ENTRY_TYPE_DATA -}; - -struct scsc_wifi_ring_buffer_entry { - u16 entry_size; /* the size of payload excluding the header. */ - u8 flags; - u8 type; - u64 timestamp; /* present if has_timestamp bit is set. */ -} __packed; - -/* set if binary entries are present */ -#define WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES 0x00000001 -/* set if ascii entries are present */ -#define WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES 0x00000002 - -/* Below events refer to the wifi_connectivity_event ring and shall be supported */ -#define WIFI_EVENT_ASSOCIATION_REQUESTED 0 // driver receives association command from kernel -#define WIFI_EVENT_AUTH_COMPLETE 1 -#define WIFI_EVENT_ASSOC_COMPLETE 2 -#define WIFI_EVENT_FW_AUTH_STARTED 3 // fw event indicating auth frames are sent -#define WIFI_EVENT_FW_ASSOC_STARTED 4 // fw event indicating assoc frames are sent -#define WIFI_EVENT_FW_RE_ASSOC_STARTED 5 // fw event indicating reassoc frames are sent -#define WIFI_EVENT_DRIVER_SCAN_REQUESTED 6 -#define WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND 7 -#define WIFI_EVENT_DRIVER_SCAN_COMPLETE 8 -#define WIFI_EVENT_G_SCAN_STARTED 9 -#define WIFI_EVENT_G_SCAN_COMPLETE 10 -#define WIFI_EVENT_DISASSOCIATION_REQUESTED 11 -#define WIFI_EVENT_RE_ASSOCIATION_REQUESTED 12 -#define WIFI_EVENT_ROAM_REQUESTED 13 -#define WIFI_EVENT_BEACON_RECEIVED 14 // received beacon from AP (event enabled - // only in verbose mode) -#define WIFI_EVENT_ROAM_SCAN_STARTED 15 // firmware has triggered a roam scan (not g-scan) -#define WIFI_EVENT_ROAM_SCAN_COMPLETE 16 // firmware has completed a roam scan (not g-scan) -#define WIFI_EVENT_ROAM_SEARCH_STARTED 17 // firmware has started searching for roam - // candidates (with reason =xx) -#define WIFI_EVENT_ROAM_SEARCH_STOPPED 18 // firmware has stopped searching for roam -// candidates (with reason =xx) -#define WIFI_EVENT_CHANNEL_SWITCH_ANOUNCEMENT 20 // received channel switch anouncement from AP -#define WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START 21 // fw start transmit eapol frame, with - // EAPOL index 1-4 -#define WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP 22 // fw gives up eapol frame, with rate, - // success/failure and number retries -#define WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED 23 // kernel queue EAPOL for transmission - // in driver with EAPOL index 1-4 -#define WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED 24 // with rate, regardless of the fact that - // EAPOL frame is accepted or rejected by fw -#define WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED 26 // with rate, and eapol index, driver has - // received EAPOL frame and will queue it up - // to wpa_supplicant -#define WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE 27 // with success/failure, parameters -#define WIFI_EVENT_BT_COEX_BT_SCO_START 28 -#define WIFI_EVENT_BT_COEX_BT_SCO_STOP 29 -#define WIFI_EVENT_BT_COEX_BT_SCAN_START 30 // for paging/scan etc., when BT starts transmiting - // twice per BT slot -#define WIFI_EVENT_BT_COEX_BT_SCAN_STOP 31 -#define WIFI_EVENT_BT_COEX_BT_HID_START 32 -#define WIFI_EVENT_BT_COEX_BT_HID_STOP 33 -#define WIFI_EVENT_ROAM_AUTH_STARTED 34 // fw sends auth frame in roaming to next candidate -#define WIFI_EVENT_ROAM_AUTH_COMPLETE 35 // fw receive auth confirm from ap -#define WIFI_EVENT_ROAM_ASSOC_STARTED 36 // firmware sends assoc/reassoc frame in - // roaming to next candidate -#define WIFI_EVENT_ROAM_ASSOC_COMPLETE 37 // firmware receive assoc/reassoc confirm from ap -#define WIFI_EVENT_G_SCAN_STOP 38 // firmware sends stop G_SCAN -#define WIFI_EVENT_G_SCAN_CYCLE_STARTED 39 // firmware indicates G_SCAN scan cycle started -#define WIFI_EVENT_G_SCAN_CYCLE_COMPLETED 40 // firmware indicates G_SCAN scan cycle completed -#define WIFI_EVENT_G_SCAN_BUCKET_STARTED 41 // firmware indicates G_SCAN scan start - // for a particular bucket -#define WIFI_EVENT_G_SCAN_BUCKET_COMPLETED 42 // firmware indicates G_SCAN scan completed for - // for a particular bucket -#define WIFI_EVENT_G_SCAN_RESULTS_AVAILABLE 43 // Event received from firmware about G_SCAN scan -// results being available -#define WIFI_EVENT_G_SCAN_CAPABILITIES 44 // Event received from firmware with G_SCAN - // capabilities -#define WIFI_EVENT_ROAM_CANDIDATE_FOUND 45 // Event received from firmware when eligible - // candidate is found -#define WIFI_EVENT_ROAM_SCAN_CONFIG 46 // Event received from firmware when roam scan - // configuration gets enabled or disabled -#define WIFI_EVENT_AUTH_TIMEOUT 47 // firmware/driver timed out authentication -#define WIFI_EVENT_ASSOC_TIMEOUT 48 // firmware/driver timed out association -#define WIFI_EVENT_MEM_ALLOC_FAILURE 49 // firmware/driver encountered allocation failure -#define WIFI_EVENT_DRIVER_PNO_ADD 50 // driver added a PNO network in firmware -#define WIFI_EVENT_DRIVER_PNO_REMOVE 51 // driver removed a PNO network in firmware -#define WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND 52 // driver received PNO networks - // found indication from firmware -#define WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED 53 // driver triggered a scan for PNO networks -#define WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND 54 // driver received scan results - // of PNO networks -#define WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE 55 // driver updated scan results from - // PNO networks to cfg80211 - -/** - * Parameters of wifi logger events are TLVs - * Event parameters tags are defined as: - */ -#define WIFI_TAG_VENDOR_SPECIFIC 0 // take a byte stream as parameter -#define WIFI_TAG_BSSID 1 // takes a 6 bytes MAC address as parameter -#define WIFI_TAG_ADDR 2 // takes a 6 bytes MAC address as parameter -#define WIFI_TAG_SSID 3 // takes a 32 bytes SSID address as parameter -#define WIFI_TAG_STATUS 4 // takes an integer as parameter -#define WIFI_TAG_CHANNEL_SPEC 5 // takes one or more wifi_channel_spec as parameter -#define WIFI_TAG_WAKE_LOCK_EVENT 6 // takes a wake_lock_event struct as parameter -#define WIFI_TAG_ADDR1 7 // takes a 6 bytes MAC address as parameter -#define WIFI_TAG_ADDR2 8 // takes a 6 bytes MAC address as parameter -#define WIFI_TAG_ADDR3 9 // takes a 6 bytes MAC address as parameter -#define WIFI_TAG_ADDR4 10 // takes a 6 bytes MAC address as parameter -#define WIFI_TAG_TSF 11 // take a 64 bits TSF value as parameter -#define WIFI_TAG_IE 12 // take one or more specific 802.11 IEs parameter, - // IEs are in turn indicated in TLV format as per - // 802.11 spec -#define WIFI_TAG_INTERFACE 13 // take interface name as parameter -#define WIFI_TAG_REASON_CODE 14 // take a reason code as per 802.11 as parameter -#define WIFI_TAG_RATE_MBPS 15 // take a wifi rate in 0.5 mbps -#define WIFI_TAG_REQUEST_ID 16 // take an integer as parameter -#define WIFI_TAG_BUCKET_ID 17 // take an integer as parameter -#define WIFI_TAG_GSCAN_PARAMS 18 // takes a wifi_scan_cmd_params struct as parameter -#define WIFI_TAG_GSCAN_CAPABILITIES 19 // takes a wifi_gscan_capabilities struct as parameter -#define WIFI_TAG_SCAN_ID 20 // take an integer as parameter -#define WIFI_TAG_RSSI 21 // take an integer as parameter -#define WIFI_TAG_CHANNEL 22 // take an integer as parameter -#define WIFI_TAG_LINK_ID 23 // take an integer as parameter -#define WIFI_TAG_LINK_ROLE 24 // take an integer as parameter -#define WIFI_TAG_LINK_STATE 25 // take an integer as parameter -#define WIFI_TAG_LINK_TYPE 26 // take an integer as parameter -#define WIFI_TAG_TSCO 27 // take an integer as parameter -#define WIFI_TAG_RSCO 28 // take an integer as parameter -#define WIFI_TAG_EAPOL_MESSAGE_TYPE 29 // take an integer as parameter - // M1-1, M2-2, M3-3, M4-4 - -struct scsc_tlv_log { - u16 tag; - u16 length; // length of value - u8 value[0]; -} __packed; - -struct scsc_wifi_ring_buffer_driver_connectivity_event { - u16 event; - struct scsc_tlv_log tlvs[0]; -} __packed; - -/** - * Ring buffer name for power events ring. note that power event are extremely frequents - * and thus should be stored in their own ring/file so as not to clobber connectivity events. - */ -struct scsc_wake_lock_event { - int status; // 0 taken, 1 released - int reason; // reason why this wake lock is taken - char name[0]; // null terminated -} __packed; - -struct scsc_wifi_power_event { - u16 event; - struct scsc_tlv_log tlvs[0]; -} __packed; - -#define PER_PACKET_ENTRY_FLAGS_DIRECTION_TX 1 /* 0: TX, 1: RX */ -#define PER_PACKET_ENTRY_FLAGS_TX_SUCCESS 2 /* pkt TX or RX/decrypt successfully */ -#define PER_PACKET_ENTRY_FLAGS_80211_HEADER 4 /* full 802.11 header or 802.3 header */ -#define PER_PACKET_ENTRY_FLAGS_PROTECTED 8 /* whether packet was encrypted */ - -struct scsc_wifi_ring_per_packet_status_entry { - u8 flags; - u8 tid; - u16 MCS; - u8 rssi; - u8 num_retries; - u16 last_transmit_rate; - u16 link_layer_transmit_sequence; - u64 firmware_entry_timestamp; - u64 start_contention_timestamp; - u64 transmit_success_timestamp; - u8 data[0]; -} __packed; - -typedef void (*on_driver_memory_dump)(char *buffer, int buffer_size, void *ctx); -typedef void (*on_firmware_memory_dump)(char *buffer, int buffer_size, void *ctx); - -/* packet fate logs */ - -#define MD5_PREFIX_LEN 4 -#define MAX_FATE_LOG_LEN 32 -#define MAX_FRAME_LEN_ETHERNET 1518 -#define MAX_FRAME_LEN_80211_MGMT 2352 // 802.11-2012 Fig. 8-34 - -typedef enum { - // Sent over air and ACKed. - TX_PKT_FATE_ACKED, - - // Sent over air but not ACKed. (Normal for broadcast/multicast.) - TX_PKT_FATE_SENT, - - // Queued within firmware, but not yet sent over air. - TX_PKT_FATE_FW_QUEUED, - - // Dropped by firmware as invalid. E.g. bad source address, bad checksum, - // or invalid for current state. - TX_PKT_FATE_FW_DROP_INVALID, - - // Dropped by firmware due to lack of buffer space. - TX_PKT_FATE_FW_DROP_NOBUFS, - - // Dropped by firmware for any other reason. Includes frames that - // were sent by driver to firmware, but unaccounted for by - // firmware. - TX_PKT_FATE_FW_DROP_OTHER, - - // Queued within driver, not yet sent to firmware. - TX_PKT_FATE_DRV_QUEUED, - - // Dropped by driver as invalid. E.g. bad source address, or - // invalid for current state. - TX_PKT_FATE_DRV_DROP_INVALID, - - // Dropped by driver due to lack of buffer space. - TX_PKT_FATE_DRV_DROP_NOBUFS, - - // Dropped by driver for any other reason. - TX_PKT_FATE_DRV_DROP_OTHER, -} wifi_tx_packet_fate; - -typedef enum { - // Valid and delivered to network stack (e.g., netif_rx()). - RX_PKT_FATE_SUCCESS, - - // Queued within firmware, but not yet sent to driver. - RX_PKT_FATE_FW_QUEUED, - - // Dropped by firmware due to host-programmable filters. - RX_PKT_FATE_FW_DROP_FILTER, - - // Dropped by firmware as invalid. E.g. bad checksum, decrypt failed, - // or invalid for current state. - RX_PKT_FATE_FW_DROP_INVALID, - - // Dropped by firmware due to lack of buffer space. - RX_PKT_FATE_FW_DROP_NOBUFS, - - // Dropped by firmware for any other reason. - RX_PKT_FATE_FW_DROP_OTHER, - - // Queued within driver, not yet delivered to network stack. - RX_PKT_FATE_DRV_QUEUED, - - // Dropped by driver due to filter rules. - RX_PKT_FATE_DRV_DROP_FILTER, - - // Dropped by driver as invalid. E.g. not permitted in current state. - RX_PKT_FATE_DRV_DROP_INVALID, - - // Dropped by driver due to lack of buffer space. - RX_PKT_FATE_DRV_DROP_NOBUFS, - - // Dropped by driver for any other reason. - RX_PKT_FATE_DRV_DROP_OTHER, -} wifi_rx_packet_fate; - -typedef enum { - FRAME_TYPE_UNKNOWN, - FRAME_TYPE_ETHERNET_II, - FRAME_TYPE_80211_MGMT, -} frame_type; - -struct scsc_frame_info { - // The type of MAC-layer frame that this frame_info holds. - // - For data frames, use FRAME_TYPE_ETHERNET_II. - // - For management frames, use FRAME_TYPE_80211_MGMT. - // - If the type of the frame is unknown, use FRAME_TYPE_UNKNOWN. - frame_type payload_type; - - // The number of bytes included in |frame_content|. If the frame - // contents are missing (e.g. RX frame dropped in firmware), - // |frame_len| should be set to 0. - size_t frame_len; - - // Host clock when this frame was received by the driver (either - // outbound from the host network stack, or inbound from the - // firmware). - // - The timestamp should be taken from a clock which includes time - // the host spent suspended (e.g. ktime_get_boottime()). - // - If no host timestamp is available (e.g. RX frame was dropped in - // firmware), this field should be set to 0. - u32 driver_timestamp_usec; - - // Firmware clock when this frame was received by the firmware - // (either outbound from the host, or inbound from a remote - // station). - // - The timestamp should be taken from a clock which includes time - // firmware spent suspended (if applicable). - // - If no firmware timestamp is available (e.g. TX frame was - // dropped by driver), this field should be set to 0. - // - Consumers of |frame_info| should _not_ assume any - // synchronization between driver and firmware clocks. - u32 firmware_timestamp_usec; - - // Actual frame content. - // - Should be provided for TX frames originated by the host. - // - Should be provided for RX frames received by the driver. - // - Optionally provided for TX frames originated by firmware. (At - // discretion of HAL implementation.) - // - Optionally provided for RX frames dropped in firmware. (At - // discretion of HAL implementation.) - // - If frame content is not provided, |frame_len| should be set - // to 0. - union { - char ethernet_ii_bytes[MAX_FRAME_LEN_ETHERNET]; - char ieee_80211_mgmt_bytes[MAX_FRAME_LEN_80211_MGMT]; - } frame_content; -}; - -typedef struct { - // Prefix of MD5 hash of |frame_inf.frame_content|. If frame - // content is not provided, prefix of MD5 hash over the same data - // that would be in frame_content, if frame content were provided. - char md5_prefix[MD5_PREFIX_LEN]; - wifi_tx_packet_fate fate; - struct scsc_frame_info frame_inf; -} __packed wifi_tx_report; - -typedef struct { - // Prefix of MD5 hash of |frame_inf.frame_content|. If frame - // content is not provided, prefix of MD5 hash over the same data - // that would be in frame_content, if frame content were provided. - char md5_prefix[MD5_PREFIX_LEN]; - wifi_rx_packet_fate fate; - struct scsc_frame_info frame_inf; -} __packed wifi_rx_report; -#endif /* _SCSC_WIFILOGGER_TYPES_H_ */ diff --git a/drivers/misc/samsung/scsc/scsc_wlbtd.c b/drivers/misc/samsung/scsc/scsc_wlbtd.c deleted file mode 100755 index 070f19c905a0..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wlbtd.c +++ /dev/null @@ -1,717 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include - -#include "scsc_wlbtd.h" - -#define MAX_TIMEOUT 30000 /* in milisecounds */ -#define WRITE_FILE_TIMEOUT 1000 /* in milisecounds */ - -/* completion to indicate when EVENT_* is done */ -static DECLARE_COMPLETION(event_done); -static DECLARE_COMPLETION(fw_panic_done); -static DECLARE_COMPLETION(write_file_done); -static DEFINE_MUTEX(write_file_lock); - -static DEFINE_MUTEX(build_type_lock); -static char *build_type; -static DEFINE_MUTEX(sable_lock); - -static struct wake_lock wlbtd_wakelock; - -/* module parameter controlling recovery handling */ -extern int disable_recovery_handling; - -const char *response_code_to_str(int response_code) -{ - switch (response_code) { - case SCSC_WLBTD_ERR_PARSE_FAILED: - return "SCSC_WLBTD_ERR_PARSE_FAILED"; - case SCSC_WLBTD_FW_PANIC_TAR_GENERATED: - return "SCSC_WLBTD_FW_PANIC_TAR_GENERATED"; - case SCSC_WLBTD_FW_PANIC_ERR_SCRIPT_FILE_NOT_FOUND: - return "SCSC_WLBTD_FW_PANIC_ERR_SCRIPT_FILE_NOT_FOUND"; - case SCSC_WLBTD_FW_PANIC_ERR_NO_DEV: - return "SCSC_WLBTD_FW_PANIC_ERR_NO_DEV"; - case SCSC_WLBTD_FW_PANIC_ERR_MMAP: - return "SCSC_WLBTD_FW_PANIC_ERR_MMAP"; - case SCSC_WLBTD_FW_PANIC_ERR_SABLE_FILE: - return "SCSC_WLBTD_FW_PANIC_ERR_SABLE_FILE"; - case SCSC_WLBTD_FW_PANIC_ERR_TAR: - return "SCSC_WLBTD_FW_PANIC_ERR_TAR"; - case SCSC_WLBTD_OTHER_SBL_GENERATED: - return "SCSC_WLBTD_OTHER_SBL_GENERATED"; - case SCSC_WLBTD_OTHER_TAR_GENERATED: - return "SCSC_WLBTD_OTHER_TAR_GENERATED"; - case SCSC_WLBTD_OTHER_ERR_SCRIPT_FILE_NOT_FOUND: - return "SCSC_WLBTD_OTHER_ERR_SCRIPT_FILE_NOT_FOUND"; - case SCSC_WLBTD_OTHER_ERR_NO_DEV: - return "SCSC_WLBTD_OTHER_ERR_NO_DEV"; - case SCSC_WLBTD_OTHER_ERR_MMAP: - return "SCSC_WLBTD_OTHER_ERR_MMAP"; - case SCSC_WLBTD_OTHER_ERR_SABLE_FILE: - return "SCSC_WLBTD_OTHER_ERR_SABLE_FILE"; - case SCSC_WLBTD_OTHER_ERR_TAR: - return "SCSC_WLBTD_OTHER_ERR_TAR"; - case SCSC_WLBTD_OTHER_IGNORE_TRIGGER: - return "SCSC_WLBTD_OTHER_IGNORE_TRIGGER"; - default: - SCSC_TAG_ERR(WLBTD, "UNKNOWN response_code %d", response_code); - return "UNKNOWN response_code"; - } -} - -/** - * This callback runs whenever the socket receives messages. - */ -static int msg_from_wlbtd_cb(struct sk_buff *skb, struct genl_info *info) -{ - int status = 0; - - if (info->attrs[1]) - SCSC_TAG_INFO(WLBTD, "ATTR_STR: %s\n", - (char *)nla_data(info->attrs[1])); - - if (info->attrs[2]) { - status = *((__u32 *)nla_data(info->attrs[2])); - if (status) - SCSC_TAG_ERR(WLBTD, "ATTR_INT: %u\n", status); - } - - complete(&event_done); - - return 0; -} - -static int msg_from_wlbtd_sable_cb(struct sk_buff *skb, struct genl_info *info) -{ - int status = 0; - const char *data = (const char *)nla_data(info->attrs[1]); - - if (info->attrs[1]) - SCSC_TAG_INFO(WLBTD, "%s\n", data); - - if (info->attrs[2]) { - status = nla_get_u16(info->attrs[2]); - SCSC_TAG_ERR(WLBTD, "%s\n", response_code_to_str(status)); - } - - /* completion cases : - * 1) FW_PANIC_TAR_GENERATED - * for trigger scsc_log_fw_panic only one response from wlbtd when - * tar done - * ---> complete fw_panic_done - * 2) for all other triggers, we get 2 responses - * a) OTHER_SBL_GENERATED - * Once .sbl is written - * ---> complete event_done - * b) OTHER_TAR_GENERATED - * 2nd time when sable tar is done - * IGNORE this response and Don't complete - * 3) OTHER_IGNORE_TRIGGER - * When we get rapid requests for SABLE generation, - * to serialise while processing current request, - * we ignore requests other than "fw_panic" in wlbtd and - * send a msg "ignoring" back to kernel. - * ---> complete event_done - * 4) FW_PANIC_ERR_* and OTHER_ERR_* - * when something failed, file not found, mmap failed, etc. - * ---> complete the completion with waiter(s) based on if it was - * a fw_panic trigger or other trigger - * 5) ERR_PARSE_FAILED - * When msg parsing fails, wlbtd doesn't know the trigger type - * ---> complete the completion with waiter(s) - */ - - switch (status) { - case SCSC_WLBTD_ERR_PARSE_FAILED: - if (!completion_done(&fw_panic_done)) { - SCSC_TAG_INFO(WLBTD, "completing fw_panic_done\n"); - complete(&fw_panic_done); - } - if (!completion_done(&event_done)) { - SCSC_TAG_INFO(WLBTD, "completing event_done\n"); - complete_all(&event_done); - } - break; - case SCSC_WLBTD_FW_PANIC_TAR_GENERATED: - case SCSC_WLBTD_FW_PANIC_ERR_TAR: - case SCSC_WLBTD_FW_PANIC_ERR_SCRIPT_FILE_NOT_FOUND: - case SCSC_WLBTD_FW_PANIC_ERR_NO_DEV: - case SCSC_WLBTD_FW_PANIC_ERR_MMAP: - case SCSC_WLBTD_FW_PANIC_ERR_SABLE_FILE: - if (!completion_done(&fw_panic_done)) { - SCSC_TAG_INFO(WLBTD, "completing fw_panic_done\n"); - complete(&fw_panic_done); - } - break; - case SCSC_WLBTD_OTHER_TAR_GENERATED: - /* ignore */ - break; - case SCSC_WLBTD_OTHER_SBL_GENERATED: - case SCSC_WLBTD_OTHER_ERR_TAR: - case SCSC_WLBTD_OTHER_ERR_SCRIPT_FILE_NOT_FOUND: - case SCSC_WLBTD_OTHER_ERR_NO_DEV: - case SCSC_WLBTD_OTHER_ERR_MMAP: - case SCSC_WLBTD_OTHER_ERR_SABLE_FILE: - case SCSC_WLBTD_OTHER_IGNORE_TRIGGER: - if (!completion_done(&event_done)) { - SCSC_TAG_INFO(WLBTD, "completing event_done\n"); - complete_all(&event_done); - } - break; - default: - SCSC_TAG_ERR(WLBTD, "UNKNOWN reponse from WLBTD\n"); - } - - return 0; -} - -static int msg_from_wlbtd_build_type_cb(struct sk_buff *skb, struct genl_info *info) -{ - if (!info->attrs[1]) { - SCSC_TAG_WARNING(WLBTD, "info->attrs[1] = NULL\n"); - return -1; - } - - if (!nla_len(info->attrs[1])) { - SCSC_TAG_WARNING(WLBTD, "nla_len = 0\n"); - return -1; - } - - mutex_lock(&build_type_lock); - if (build_type) { - SCSC_TAG_WARNING(WLBTD, "ro.build.type = %s\n", build_type); - mutex_unlock(&build_type_lock); - return 0; - } - /* nla_len includes trailing zero. Tested.*/ - build_type = kmalloc(info->attrs[1]->nla_len, GFP_KERNEL); - if (!build_type) { - SCSC_TAG_WARNING(WLBTD, "kmalloc failed: build_type = NULL\n"); - mutex_unlock(&build_type_lock); - return -1; - } - memcpy(build_type, (char *)nla_data(info->attrs[1]), info->attrs[1]->nla_len); - SCSC_TAG_WARNING(WLBTD, "ro.build.type = %s\n", build_type); - mutex_unlock(&build_type_lock); - return 0; - -} - -static int msg_from_wlbtd_write_file_cb(struct sk_buff *skb, struct genl_info *info) -{ - if (info->attrs[3]) - SCSC_TAG_INFO(WLBTD, "%s\n", (char *)nla_data(info->attrs[3])); - - complete(&write_file_done); - return 0; -} - -/** - * Here you can define some constraints for the attributes so Linux will - * validate them for you. - */ -static struct nla_policy policies[] = { - [ATTR_STR] = { .type = NLA_STRING, }, - [ATTR_INT] = { .type = NLA_U32, }, -}; - -static struct nla_policy policy_sable[] = { - [ATTR_INT] = { .type = NLA_U16, }, - [ATTR_INT8] = { .type = NLA_U8, }, -}; - -static struct nla_policy policies_build_type[] = { - [ATTR_STR] = { .type = NLA_STRING, }, -}; - -static struct nla_policy policy_write_file[] = { - [ATTR_PATH] = { .type = NLA_STRING, }, - [ATTR_CONTENT] = { .type = NLA_STRING, }, -}; - - -/** - * Actual message type definition. - */ -const struct genl_ops scsc_ops[] = { - { - .cmd = EVENT_SCSC, - .flags = 0, - .policy = policies, - .doit = msg_from_wlbtd_cb, - .dumpit = NULL, - }, - { - .cmd = EVENT_SYSTEM_PROPERTY, - .flags = 0, - .policy = policies_build_type, - .doit = msg_from_wlbtd_build_type_cb, - .dumpit = NULL, - }, - { - .cmd = EVENT_SABLE, - .flags = 0, - .policy = policy_sable, - .doit = msg_from_wlbtd_sable_cb, - .dumpit = NULL, - }, - { - .cmd = EVENT_WRITE_FILE, - .flags = 0, - .policy = policy_write_file, - .doit = msg_from_wlbtd_write_file_cb, - .dumpit = NULL, - }, - -}; - -/* The netlink family */ -static struct genl_family scsc_nlfamily = { - .id = 0, /* Don't bother with a hardcoded ID */ - .name = "scsc_mdp_family", /* Have users key off the name instead */ - .hdrsize = 0, /* No private header */ - .version = 1, - .maxattr = __ATTR_MAX, - .module = THIS_MODULE, - .ops = scsc_ops, - .n_ops = ARRAY_SIZE(scsc_ops), - .mcgrps = scsc_mcgrp, - .n_mcgrps = ARRAY_SIZE(scsc_mcgrp), -}; - -int scsc_wlbtd_get_and_print_build_type(void) -{ - struct sk_buff *skb; - void *msg; - int rc = 0; - - SCSC_TAG_DEBUG(WLBTD, "start\n"); - wake_lock(&wlbtd_wakelock); - - /* check if the value wasn't cached yet */ - mutex_lock(&build_type_lock); - if (build_type) { - SCSC_TAG_WARNING(WLBTD, "ro.build.type = %s\n", build_type); - SCSC_TAG_DEBUG(WLBTD, "sync end\n"); - mutex_unlock(&build_type_lock); - goto done; - } - mutex_unlock(&build_type_lock); - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb) { - SCSC_TAG_ERR(WLBTD, "Failed to construct message\n"); - goto error; - } - - SCSC_TAG_INFO(WLBTD, "create message\n"); - msg = genlmsg_put(skb, - 0, // PID is whatever - 0, // Sequence number (don't care) - &scsc_nlfamily, // Pointer to family struct - 0, // Flags - EVENT_SYSTEM_PROPERTY // Generic netlink command - ); - if (!msg) { - SCSC_TAG_ERR(WLBTD, "Failed to create message\n"); - goto error; - } - rc = nla_put_string(skb, ATTR_STR, "ro.build.type"); - if (rc) { - SCSC_TAG_ERR(WLBTD, "nla_put_string failed. rc = %d\n", rc); - genlmsg_cancel(skb, msg); - goto error; - } - genlmsg_end(skb, msg); - - SCSC_TAG_INFO(WLBTD, "finalize & send msg\n"); - rc = genlmsg_multicast_allns(&scsc_nlfamily, skb, 0, 0, GFP_KERNEL); - - if (rc) { - SCSC_TAG_ERR(WLBTD, "failed to send message. rc = %d\n", rc); - goto error; - } - - SCSC_TAG_DEBUG(WLBTD, "async end\n"); -done: - wake_unlock(&wlbtd_wakelock); - return rc; - -error: - if (rc == -ESRCH) { - /* If no one registered to scsc_mdp_mcgrp (e.g. in case wlbtd - * is not running) genlmsg_multicast_allns returns -ESRCH. - * Ignore and return. - */ - SCSC_TAG_WARNING(WLBTD, "WLBTD not running ?\n"); - wake_unlock(&wlbtd_wakelock); - return rc; - } - /* free skb */ - nlmsg_free(skb); - wake_unlock(&wlbtd_wakelock); - return -1; -} - -int wlbtd_write_file(const char *file_path, const char *file_content) -{ -#ifdef CONFIG_SCSC_WRITE_INFO_FILE_WLBTD - struct sk_buff *skb; - void *msg; - int rc = 0; - unsigned long completion_jiffies = 0; - unsigned long max_timeout_jiffies = msecs_to_jiffies(WRITE_FILE_TIMEOUT); - - SCSC_TAG_DEBUG(WLBTD, "start\n"); - - mutex_lock(&write_file_lock); - wake_lock(&wlbtd_wakelock); - - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb) { - SCSC_TAG_ERR(WLBTD, "Failed to construct message\n"); - goto error; - } - - SCSC_TAG_INFO(WLBTD, "create message to write %s\n", file_path); - msg = genlmsg_put(skb, - 0, // PID is whatever - 0, // Sequence number (don't care) - &scsc_nlfamily, // Pointer to family struct - 0, // Flags - EVENT_WRITE_FILE// Generic netlink command - ); - if (!msg) { - SCSC_TAG_ERR(WLBTD, "Failed to create message\n"); - goto error; - } - - SCSC_TAG_DEBUG(WLBTD, "add values to msg\n"); - rc = nla_put_string(skb, ATTR_PATH, file_path); - if (rc) { - SCSC_TAG_ERR(WLBTD, "nla_put_u32 failed. rc = %d\n", rc); - genlmsg_cancel(skb, msg); - goto error; - } - - rc = nla_put_string(skb, ATTR_CONTENT, file_content); - if (rc) { - SCSC_TAG_ERR(WLBTD, "nla_put_string failed. rc = %d\n", rc); - genlmsg_cancel(skb, msg); - goto error; - } - - genlmsg_end(skb, msg); - - SCSC_TAG_INFO(WLBTD, "finalize & send msg\n"); - /* genlmsg_multicast_allns() frees skb */ - rc = genlmsg_multicast_allns(&scsc_nlfamily, skb, 0, 0, GFP_KERNEL); - - if (rc) { - if (rc == -ESRCH) { - /* If no one registered to scsc_mcgrp (e.g. in case - * wlbtd is not running) genlmsg_multicast_allns - * returns -ESRCH. Ignore and return. - */ - SCSC_TAG_WARNING(WLBTD, "WLBTD not running ?\n"); - goto done; - } - SCSC_TAG_ERR(WLBTD, "Failed to send message. rc = %d\n", rc); - goto done; - } - - SCSC_TAG_INFO(WLBTD, "waiting for completion\n"); - /* wait for script to finish */ - completion_jiffies = wait_for_completion_timeout(&write_file_done, - max_timeout_jiffies); - - if (completion_jiffies == 0) - SCSC_TAG_ERR(WLBTD, "wait for completion timed out !\n"); - else { - completion_jiffies = jiffies_to_msecs(max_timeout_jiffies - completion_jiffies); - - SCSC_TAG_INFO(WLBTD, "written %s in %dms\n", file_path, - completion_jiffies ? completion_jiffies : 1); - } - - /* reinit so completion can be re-used */ - reinit_completion(&write_file_done); - - SCSC_TAG_DEBUG(WLBTD, "end\n"); -done: - wake_unlock(&wlbtd_wakelock); - mutex_unlock(&write_file_lock); - return rc; - -error: - /* free skb */ - nlmsg_free(skb); - - wake_unlock(&wlbtd_wakelock); - mutex_unlock(&write_file_lock); - return -1; -#else /* CONFIG_SCSC_WRITE_INFO_FILE_WLBTD */ - return 0; /* stub */ -#endif -} -EXPORT_SYMBOL(wlbtd_write_file); - -int call_wlbtd_sable(u8 trigger_code, u16 reason_code) -{ - struct sk_buff *skb; - void *msg; - int rc = 0; - unsigned long completion_jiffies = 0; - unsigned long max_timeout_jiffies = msecs_to_jiffies(MAX_TIMEOUT); - - mutex_lock(&sable_lock); - wake_lock(&wlbtd_wakelock); - - SCSC_TAG_INFO(WLBTD, "start:trigger - %s\n", - scsc_get_trigger_str((int)trigger_code)); - - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb) { - SCSC_TAG_ERR(WLBTD, "Failed to construct message\n"); - goto error; - } - - SCSC_TAG_DEBUG(WLBTD, "create message\n"); - msg = genlmsg_put(skb, - 0, // PID is whatever - 0, // Sequence number (don't care) - &scsc_nlfamily, // Pointer to family struct - 0, // Flags - EVENT_SABLE // Generic netlink command - ); - if (!msg) { - SCSC_TAG_ERR(WLBTD, "Failed to create message\n"); - goto error; - } - SCSC_TAG_DEBUG(WLBTD, "add values to msg\n"); - rc = nla_put_u16(skb, ATTR_INT, reason_code); - if (rc) { - SCSC_TAG_ERR(WLBTD, "nla_put_u16 failed. rc = %d\n", rc); - genlmsg_cancel(skb, msg); - goto error; - } - - rc = nla_put_u8(skb, ATTR_INT8, trigger_code); - if (rc) { - SCSC_TAG_ERR(WLBTD, "nla_put_u8 failed. rc = %d\n", rc); - genlmsg_cancel(skb, msg); - goto error; - } - - genlmsg_end(skb, msg); - - SCSC_TAG_DEBUG(WLBTD, "finalize & send msg\n"); - /* genlmsg_multicast_allns() frees skb */ - rc = genlmsg_multicast_allns(&scsc_nlfamily, skb, 0, 0, GFP_KERNEL); - - if (rc) { - if (rc == -ESRCH) { - /* If no one registered to scsc_mcgrp (e.g. in case - * wlbtd is not running) genlmsg_multicast_allns - * returns -ESRCH. Ignore and return. - */ - SCSC_TAG_WARNING(WLBTD, "WLBTD not running ?\n"); - goto done; - } - SCSC_TAG_ERR(WLBTD, "Failed to send message. rc = %d\n", rc); - goto done; - } - - SCSC_TAG_INFO(WLBTD, "waiting for completion\n"); - - /* wait for script to finish */ - if (trigger_code == SCSC_LOG_FW_PANIC) - completion_jiffies = wait_for_completion_timeout(&fw_panic_done, - max_timeout_jiffies); - else - completion_jiffies = wait_for_completion_timeout(&event_done, - max_timeout_jiffies); - - if (completion_jiffies) { - completion_jiffies = max_timeout_jiffies - completion_jiffies; - SCSC_TAG_INFO(WLBTD, "sable generated in %dms\n", - (int)jiffies_to_msecs(completion_jiffies) ? : 1); - } else - SCSC_TAG_ERR(WLBTD, "wait for completion timed out for %s\n", - scsc_get_trigger_str((int)trigger_code)); - - /* reinit so completion can be re-used */ - if (trigger_code == SCSC_LOG_FW_PANIC) - reinit_completion(&fw_panic_done); - else - reinit_completion(&event_done); - - SCSC_TAG_INFO(WLBTD, " end:trigger - %s\n", - scsc_get_trigger_str((int)trigger_code)); - -done: - wake_unlock(&wlbtd_wakelock); - mutex_unlock(&sable_lock); - return rc; - -error: - /* free skb */ - nlmsg_free(skb); - wake_unlock(&wlbtd_wakelock); - mutex_unlock(&sable_lock); - - return -1; -} -EXPORT_SYMBOL(call_wlbtd_sable); - -void scsc_wlbtd_wait_for_sable_logging(void) -{ - unsigned long completion_jiffies = 0; - unsigned long max_timeout_jiffies = msecs_to_jiffies(MAX_TIMEOUT); - /* Just waits for the log collection not tarring */ - completion_jiffies = wait_for_completion_timeout(&event_done, - max_timeout_jiffies); - if (!completion_jiffies) - SCSC_TAG_ERR(WLBTD, "wait for sable logging timed out !\n"); -} -EXPORT_SYMBOL(scsc_wlbtd_wait_for_sable_logging); - - -int call_wlbtd(const char *script_path) -{ - struct sk_buff *skb; - void *msg; - int rc = 0; - unsigned long completion_jiffies = 0; - unsigned long max_timeout_jiffies = msecs_to_jiffies(MAX_TIMEOUT); - - SCSC_TAG_DEBUG(WLBTD, "start\n"); - - wake_lock(&wlbtd_wakelock); - - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb) { - SCSC_TAG_ERR(WLBTD, "Failed to construct message\n"); - goto error; - } - - SCSC_TAG_INFO(WLBTD, "create message to run %s\n", script_path); - msg = genlmsg_put(skb, - 0, // PID is whatever - 0, // Sequence number (don't care) - &scsc_nlfamily, // Pointer to family struct - 0, // Flags - EVENT_SCSC // Generic netlink command - ); - if (!msg) { - SCSC_TAG_ERR(WLBTD, "Failed to create message\n"); - goto error; - } - - SCSC_TAG_DEBUG(WLBTD, "add values to msg\n"); - rc = nla_put_u32(skb, ATTR_INT, 9); - if (rc) { - SCSC_TAG_ERR(WLBTD, "nla_put_u32 failed. rc = %d\n", rc); - genlmsg_cancel(skb, msg); - goto error; - } - - rc = nla_put_string(skb, ATTR_STR, script_path); - if (rc) { - SCSC_TAG_ERR(WLBTD, "nla_put_string failed. rc = %d\n", rc); - genlmsg_cancel(skb, msg); - goto error; - } - - genlmsg_end(skb, msg); - - SCSC_TAG_INFO(WLBTD, "finalize & send msg\n"); - /* genlmsg_multicast_allns() frees skb */ - rc = genlmsg_multicast_allns(&scsc_nlfamily, skb, 0, 0, GFP_KERNEL); - - if (rc) { - if (rc == -ESRCH) { - /* If no one registered to scsc_mcgrp (e.g. in case - * wlbtd is not running) genlmsg_multicast_allns - * returns -ESRCH. Ignore and return. - */ - SCSC_TAG_WARNING(WLBTD, "WLBTD not running ?\n"); - goto done; - } - SCSC_TAG_ERR(WLBTD, "Failed to send message. rc = %d\n", rc); - goto done; - } - - SCSC_TAG_INFO(WLBTD, "waiting for completion\n"); - - /* wait for script to finish */ - completion_jiffies = wait_for_completion_timeout(&event_done, - max_timeout_jiffies); - - if (completion_jiffies) { - - completion_jiffies = max_timeout_jiffies - completion_jiffies; - SCSC_TAG_INFO(WLBTD, "done in %dms\n", - (int)jiffies_to_msecs(completion_jiffies) ? : 1); - } else - SCSC_TAG_ERR(WLBTD, "wait for completion timed out !\n"); - - /* reinit so completion can be re-used */ - reinit_completion(&event_done); - - SCSC_TAG_DEBUG(WLBTD, "end\n"); - -done: - wake_unlock(&wlbtd_wakelock); - return rc; - -error: - /* free skb */ - nlmsg_free(skb); - wake_unlock(&wlbtd_wakelock); - - return -1; -} -EXPORT_SYMBOL(call_wlbtd); - -int scsc_wlbtd_init(void) -{ - int r = 0; - - wake_lock_init(&wlbtd_wakelock, WAKE_LOCK_SUSPEND, "wlbtd_wl"); - init_completion(&event_done); - init_completion(&fw_panic_done); - init_completion(&write_file_done); - - /* register the family so that wlbtd can bind */ - r = genl_register_family(&scsc_nlfamily); - if (r) { - SCSC_TAG_ERR(WLBTD, "Failed to register family. (%d)\n", r); - return -1; - } - - return r; -} - -int scsc_wlbtd_deinit(void) -{ - int ret = 0; - - /* unregister family */ - ret = genl_unregister_family(&scsc_nlfamily); - if (ret) { - SCSC_TAG_ERR(WLBTD, "genl_unregister_family failed (%d)\n", - ret); - return -1; - } - kfree(build_type); - build_type = NULL; - wake_lock_destroy(&wlbtd_wakelock); - - return ret; -} diff --git a/drivers/misc/samsung/scsc/scsc_wlbtd.h b/drivers/misc/samsung/scsc/scsc_wlbtd.h deleted file mode 100644 index fa265e18fdd6..000000000000 --- a/drivers/misc/samsung/scsc/scsc_wlbtd.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include -#include -#include - -/* module parameter value to indicate control of recovery via .memdump.info file */ -#define MEMDUMP_FILE_FOR_RECOVERY 2 -/* content of .memdump.info file indicating to panic kernel */ -#define MEMDUMP_FILE_KERNEL_PANIC 3 - -/** - * Attributes are fields of data your messages will contain. - * The designers of Netlink really want you to use these instead of just dumping - * data to the packet payload. - */ -enum attributes { - /* The first one has to be a throwaway empty attribute */ - ATTR_UNSPEC, - - ATTR_STR, - ATTR_INT, - ATTR_PATH, - ATTR_CONTENT, - ATTR_INT8, - - /* This must be last! */ - __ATTR_MAX, -}; - -/** - * Message type codes. - */ -enum events { - /* must be first */ - EVENT_UNSPEC, - - EVENT_SCSC, - EVENT_SYSTEM_PROPERTY, - EVENT_WRITE_FILE, - EVENT_SABLE, - /* This must be last! */ - __EVENT_MAX, -}; - -enum scsc_wlbtd_response_codes { - /* NOTE: keep the enum in sync with userspace wlbtd */ - /* parse failed */ - SCSC_WLBTD_ERR_PARSE_FAILED, - - /* fw_panic trigger */ - SCSC_WLBTD_FW_PANIC_TAR_GENERATED, - SCSC_WLBTD_FW_PANIC_ERR_SCRIPT_FILE_NOT_FOUND, - SCSC_WLBTD_FW_PANIC_ERR_NO_DEV, - SCSC_WLBTD_FW_PANIC_ERR_MMAP, - SCSC_WLBTD_FW_PANIC_ERR_SABLE_FILE, - SCSC_WLBTD_FW_PANIC_ERR_TAR, - - /* other triggers */ - SCSC_WLBTD_OTHER_SBL_GENERATED, - SCSC_WLBTD_OTHER_TAR_GENERATED, - SCSC_WLBTD_OTHER_ERR_SCRIPT_FILE_NOT_FOUND, - SCSC_WLBTD_OTHER_ERR_NO_DEV, - SCSC_WLBTD_OTHER_ERR_MMAP, - SCSC_WLBTD_OTHER_ERR_SABLE_FILE, - SCSC_WLBTD_OTHER_ERR_TAR, - SCSC_WLBTD_OTHER_IGNORE_TRIGGER, -}; - -static const struct genl_multicast_group scsc_mcgrp[] = { - { .name = "scsc_mdp_grp", }, -}; - -int scsc_wlbtd_init(void); -int scsc_wlbtd_deinit(void); -int call_wlbtd(const char *script_path); -int wlbtd_write_file(const char *path, const char *content); -int call_wlbtd_sable(u8 trigger_code, u16 reason_code); -void scsc_wlbtd_wait_for_sable_logging(void); -int scsc_wlbtd_get_and_print_build_type(void); diff --git a/drivers/misc/samsung/scsc/servman_messages.h b/drivers/misc/samsung/scsc/servman_messages.h deleted file mode 100644 index 8fb4527e670d..000000000000 --- a/drivers/misc/samsung/scsc/servman_messages.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef SERVMAN_MESSAGES_H__ -#define SERVMAN_MESSAGES_H__ - -#include -/** - * Maxwell Service Management Messages. - * - * TODO: common defn with host, generated. - */ -enum { - SM_MSG_START_REQ, - SM_MSG_START_CFM, - SM_MSG_STOP_REQ, - SM_MSG_STOP_CFM, -} sm_msg; - -/* Transport format for service management messages across the - * Maxwell management transport. - * - * TODO: common defn with host, generated. - */ -struct sm_msg_packet { - uint8_t service_id; - uint8_t msg; - scsc_mifram_ref optional_data; -} __packed; - - -#endif /* SERVMAN_MESSAGES_H__ */ diff --git a/drivers/misc/samsung/scsc/srvman.h b/drivers/misc/samsung/scsc/srvman.h deleted file mode 100755 index c981280f6873..000000000000 --- a/drivers/misc/samsung/scsc/srvman.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef _SRVMAN_H -#define _SRVMAN_H - -#ifdef CONFIG_ANDROID -#include -#endif - -#include "scsc/scsc_mx.h" - -struct srvman; - -void srvman_init(struct srvman *srvman, struct scsc_mx *mx); -int srvman_suspend_services(struct srvman *srvman); -int srvman_resume_services(struct srvman *srvman); -void srvman_freeze_services(struct srvman *srvman, struct mx_syserr_decode *syserr); -void srvman_freeze_sub_system(struct srvman *srvman, struct mx_syserr_decode *syserr); -void srvman_unfreeze_services(struct srvman *srvman, u16 scsc_panic_code); -void srvman_unfreeze_sub_system(struct srvman *srvman, struct mx_syserr_decode *syserr); -u8 srvman_notify_sub_system(struct srvman *srvman, struct mx_syserr_decode *syserr); -void srvman_set_error(struct srvman *srvman); -void srvman_clear_error(struct srvman *srvman); -void srvman_deinit(struct srvman *srvman); - -struct srvman { - struct scsc_mx *mx; - struct list_head service_list; - struct mutex service_list_mutex; - struct mutex api_access_mutex; - bool error; -#ifdef CONFIG_ANDROID - struct wake_lock sm_wake_lock; -#endif -}; - - -#endif diff --git a/drivers/misc/samsung/scsc/suspendmon.c b/drivers/misc/samsung/scsc/suspendmon.c deleted file mode 100644 index b0c27ed28a56..000000000000 --- a/drivers/misc/samsung/scsc/suspendmon.c +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -#include - -#include "suspendmon.h" -#include "scsc_mif_abs.h" -#include "mxman.h" - -static int suspendmon_suspend(struct scsc_mif_abs *mif, void *data) -{ - struct suspendmon *suspendmon = (struct suspendmon *)data; - - SCSC_TAG_DEBUG(MXMAN, "suspendmon=%p suspendmon->mx=%p mxman=%p\n", - suspendmon, suspendmon->mx, scsc_mx_get_mxman(suspendmon->mx)); - - return mxman_suspend(scsc_mx_get_mxman(suspendmon->mx)); -} - -static void suspendmon_resume(struct scsc_mif_abs *mif, void *data) -{ - struct suspendmon *suspendmon = (struct suspendmon *)data; - - SCSC_TAG_DEBUG(MXMAN, "suspendmon=%p suspendmon->mx=%p mxman=%p\n", - suspendmon, suspendmon->mx, scsc_mx_get_mxman(suspendmon->mx)); - - mxman_resume(scsc_mx_get_mxman(suspendmon->mx)); -} - -void suspendmon_init(struct suspendmon *suspendmon, struct scsc_mx *mx) -{ - struct scsc_mif_abs *mif; - - suspendmon->mx = mx; - mif = scsc_mx_get_mif_abs(mx); - - /* register callbacks with mif abstraction */ - if (mif->suspend_reg_handler) - mif->suspend_reg_handler(mif, suspendmon_suspend, suspendmon_resume, (void *)suspendmon); -} - -void suspendmon_deinit(struct suspendmon *suspendmon) -{ - struct scsc_mif_abs *mif; - - mif = scsc_mx_get_mif_abs(suspendmon->mx); - - if (mif->suspend_unreg_handler) - mif->suspend_unreg_handler(mif); -} diff --git a/drivers/misc/samsung/scsc/suspendmon.h b/drivers/misc/samsung/scsc/suspendmon.h deleted file mode 100644 index d68e99e66284..000000000000 --- a/drivers/misc/samsung/scsc/suspendmon.h +++ /dev/null @@ -1,23 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - ****************************************************************************/ - -/* Baroque suspend/resume handler registration interface */ - -#ifndef _SUSPENDMON_H -#define _SUSPENDMON_H - -#include "mxman.h" - -struct suspendmon; - -void suspendmon_init(struct suspendmon *suspendmon, struct scsc_mx *mx); -void suspendmon_deinit(struct suspendmon *suspendmon); - -struct suspendmon { - struct scsc_mx *mx; -}; - -#endif /* _SUSPENDMON_H */ diff --git a/drivers/misc/samsung/scsc_bt/Kconfig b/drivers/misc/samsung/scsc_bt/Kconfig deleted file mode 100644 index 9be9a00cd86e..000000000000 --- a/drivers/misc/samsung/scsc_bt/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -config SCSC_BT - tristate "SCSC MX BT support" - depends on SCSC_CORE - -config SCSC_BT_BLUEZ - default N - tristate "SCSC MX BlueZ support" - depends on SCSC_CORE - -config SCSC_ANT - default N - tristate "SCSC MX ANT support" - depends on SCSC_CORE - ---help--- - This module adds support for using a ANT character device. - -config SCSC_BT_ADDRESS_IN_FILE - default N - tristate "SCSC MX BT support" - depends on SCSC_CORE - ---help--- - Allow BT address to be read from a file - -config SCSC_BT_ADDRESS_FILENAME - string "BT address filename" - depends on SCSC_CORE - default "/mnt/vendor/efs/bluetooth/bt_addr" - ---help--- - Select the named BT address override file. diff --git a/drivers/misc/samsung/scsc_bt/Makefile b/drivers/misc/samsung/scsc_bt/Makefile deleted file mode 100644 index c6ae27153ad2..000000000000 --- a/drivers/misc/samsung/scsc_bt/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# Needed since this subdir is symlinked in the main Kernel tree -# without this our samsung subdir is NOT cleaned. -clean-files := *.o *.ko - -# -# Maxwell BT -obj-$(CONFIG_SCSC_BT) += scsc_bt.o -scsc_bt-y += scsc_bt_module.o scsc_shm.o scsc_avdtp_detect.o -scsc_bt-$(CONFIG_SCSC_BT_BLUEZ) += scsc_bluez.o -scsc_bt-$(CONFIG_SCSC_ANT) += scsc_ant.o - -ccflags-y += $(CONFIG_SAMSUNG_MAXWELL_EXTRA) -## See sibling scsc/ Makefile for an explanation of the reasons of -## the following ifeq/else -ifeq ($(CONFIG_SCSC_LOGRING), m) -ccflags-y += -DCONFIG_SCSC_PRINTK -else -ccflags-$(CONFIG_SCSC_LOGRING) += -DCONFIG_SCSC_PRINTK -endif - -ifeq ($(CONFIG_SCSC_BT_BLUEZ), m) -ccflags-y += -DCONFIG_SCSC_BT_BLUEZ -else -ccflags-$(CONFIG_SCSC_BT_BLUEZ) += -DCONFIG_SCSC_BT_BLUEZ -endif - -ifeq ($(CONFIG_SCSC_ANT), m) -ccflags-y += -DCONFIG_SCSC_ANT -else -ccflags-$(CONFIG_SCSC_ANT) += -DCONFIG_SCSC_ANT -endif diff --git a/drivers/misc/samsung/scsc_bt/scsc_ant.c b/drivers/misc/samsung/scsc_bt/scsc_ant.c deleted file mode 100644 index 6b10c57e26fb..000000000000 --- a/drivers/misc/samsung/scsc_bt/scsc_ant.c +++ /dev/null @@ -1,676 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd - * - ****************************************************************************/ - -/* MX BT shared memory interface */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "scsc_bt_priv.h" -#include "scsc_shm.h" -#include "scsc_bt_hci.h" - -static u8 ant_write_buffer[ASMHCP_BUFFER_SIZE]; - -static void scsc_ant_shm_irq_handler(int irqbit, void *data) -{ - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(ant_service.service, irqbit); - - ant_service.interrupt_count++; - - /* Wake the reader operation */ - if (ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_write != - ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_read || - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_write != - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_read || - atomic_read(&ant_service.error_count) != 0 || - ant_service.asmhcp_protocol->header.panic_deathbed_confession) { - ant_service.interrupt_read_count++; - - wake_lock_timeout(&ant_service.read_wake_lock, HZ); - wake_up(&ant_service.read_wait); - } - - if (ant_service.asmhcp_protocol->header.mailbox_data_driv_ctr_write == - ant_service.asmhcp_protocol->header.mailbox_data_driv_ctr_read && - ant_service.asmhcp_protocol->header.mailbox_cmd_driv_ctr_write == - ant_service.asmhcp_protocol->header.mailbox_cmd_driv_ctr_read) { - ant_service.interrupt_write_count++; - - if (wake_lock_active(&ant_service.write_wake_lock)) { - ant_service.write_wake_unlock_count++; - wake_unlock(&ant_service.write_wake_lock); - } - } -} - -/* Assign firmware/host interrupts */ -static void scsc_ant_shm_init_interrupt(void) -{ - /* To-host f/w IRQ allocations and ISR registrations */ - ant_service.asmhcp_protocol->header.bg_to_ap_int_src = - scsc_service_mifintrbit_register_tohost(ant_service.service, scsc_ant_shm_irq_handler, NULL); - - /* From-host f/w IRQ allocations */ - ant_service.asmhcp_protocol->header.ap_to_bg_int_src = - scsc_service_mifintrbit_alloc_fromhost(ant_service.service, SCSC_MIFINTR_TARGET_R4); - - SCSC_TAG_DEBUG(BT_COMMON, "Registered to-host IRQ bit %d, from-host IRQ bit %d\n", - ant_service.asmhcp_protocol->header.bg_to_ap_int_src, - ant_service.asmhcp_protocol->header.ap_to_bg_int_src); -} - -static ssize_t scsc_shm_ant_cmd_write(const unsigned char *data, size_t count) -{ - /* Store the read/write pointer on the stack since both are placed in unbuffered/uncached memory */ - uint32_t tr_read = ant_service.asmhcp_protocol->header.mailbox_cmd_driv_ctr_read; - uint32_t tr_write = ant_service.asmhcp_protocol->header.mailbox_cmd_driv_ctr_write; - - struct ASMHCP_TD_CONTROL *td = &ant_service.asmhcp_protocol->cmd_driver_controller_transfer_ring[tr_write]; - /* Temp vars */ - SCSC_TAG_DEBUG(BT_H4, "ANT_COMMAND_PKT (len=%zu, read=%u, write=%u)\n", - count, tr_read, tr_write); - - /* Index out of bounds check */ - if (tr_read >= ASMHCP_TRANSFER_RING_CMD_SIZE || tr_write >= ASMHCP_TRANSFER_RING_CMD_SIZE) { - SCSC_TAG_ERR(BT_H4, - "ANT_COMMAND_PKT - Index out of bounds (tr_read=%u, tr_write=%u)\n", - tr_read, tr_write); - atomic_inc(&ant_service.error_count); - return -EIO; - } - - /* Does the transfer ring have room for an entry */ - if (BSMHCP_HAS_ROOM(tr_write, tr_read, ASMHCP_TRANSFER_RING_CMD_SIZE)) { - /* Fill the transfer descriptor with the ANT command data */ - memcpy(td->data, data, count); - td->length = (u16)count; - - /* Ensure the wake lock is acquired */ - if (!wake_lock_active(&ant_service.write_wake_lock)) { - ant_service.write_wake_lock_count++; - wake_lock(&ant_service.write_wake_lock); - } - - /* Increase the write pointer */ - BSMHCP_INCREASE_INDEX(tr_write, ASMHCP_TRANSFER_RING_CMD_SIZE); - ant_service.asmhcp_protocol->header.mailbox_cmd_driv_ctr_write = tr_write; - - /* Memory barrier to ensure out-of-order execution is completed */ - mmiowb(); - - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set( - ant_service.service, - ant_service.asmhcp_protocol->header.ap_to_bg_int_src, - SCSC_MIFINTR_TARGET_R4); - } else { - /* Transfer ring full. Only happens if the user attempt to send more ANT command packets than - * available credits - */ - count = 0; - } - - return count; -} - -static ssize_t scsc_shm_ant_data_write(const unsigned char *data, size_t count) -{ - /* Store the read/write pointer on the stack since both are placed in unbuffered/uncached memory */ - uint32_t tr_read = ant_service.asmhcp_protocol->header.mailbox_data_driv_ctr_read; - uint32_t tr_write = ant_service.asmhcp_protocol->header.mailbox_data_driv_ctr_write; - - /* Temp vars */ - struct ASMHCP_TD_CONTROL *td = &ant_service.asmhcp_protocol->data_driver_controller_transfer_ring[tr_write]; - - SCSC_TAG_DEBUG(BT_H4, "ANT_DATA_PKT (len=%zu, read=%u, write=%u)\n", - count, tr_read, tr_write); - - /* Index out of bounds check */ - if (tr_read >= ASMHCP_TRANSFER_RING_DATA_SIZE || tr_write >= ASMHCP_TRANSFER_RING_DATA_SIZE) { - SCSC_TAG_ERR( - BT_H4, - "ANT_DATA_PKT - Index out of bounds (tr_read=%u, tr_write=%u)\n", - tr_read, tr_write); - atomic_inc(&ant_service.error_count); - return -EIO; - } - - /* Does the transfer ring have room for an entry */ - if (BSMHCP_HAS_ROOM(tr_write, tr_read, ASMHCP_TRANSFER_RING_DATA_SIZE)) { - /* Fill the transfer descriptor with the ANT command data */ - memcpy(td->data, data, count); - td->length = (u16)count; - - /* Ensure the wake lock is acquired */ - if (!wake_lock_active(&ant_service.write_wake_lock)) { - ant_service.write_wake_lock_count++; - wake_lock(&ant_service.write_wake_lock); - } - - /* Increase the write pointer */ - BSMHCP_INCREASE_INDEX(tr_write, ASMHCP_TRANSFER_RING_DATA_SIZE); - ant_service.asmhcp_protocol->header.mailbox_data_driv_ctr_write = tr_write; - - /* Memory barrier to ensure out-of-order execution is completed */ - mmiowb(); - - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set( - ant_service.service, - ant_service.asmhcp_protocol->header.ap_to_bg_int_src, - SCSC_MIFINTR_TARGET_R4); - } - else - /* Transfer ring full */ - count = 0; - - return count; -} - -static ssize_t scsc_ant_copy_td_to_buffer(char __user *buf, size_t len, struct ASMHCP_TD_CONTROL *td) -{ - ssize_t ret = 0; - ssize_t consumed = 0; - size_t copy_len = 0; - - SCSC_TAG_DEBUG(BT_H4, "td (length=%u), len=%zu, read_offset=%zu\n", - td->length, len, ant_service.read_offset); - - /* Has the header been copied to userspace (aka is this the start of the copy operation) */ - if (ant_service.read_offset < ANT_HEADER_LENGTH) { - /* Calculate the amount of data that can be transferred */ - copy_len = min(ANT_HEADER_LENGTH - ant_service.read_offset, len); - - if (td->data[1] + ANT_HEADER_LENGTH + 1 != td->length) { - SCSC_TAG_ERR(BT_H4, "Firmware sent invalid ANT cmd/data\n"); - atomic_inc(&ant_service.error_count); - ret = -EFAULT; - } - /* Copy the ANT header to the userspace buffer */ - ret = copy_to_user(buf, &td->data[ant_service.read_offset], copy_len); - if (ret == 0) { - /* All good - Update our consumed information */ - consumed = copy_len; - ant_service.read_offset += copy_len; - SCSC_TAG_DEBUG(BT_H4, - "copied header: read_offset=%zu, consumed=%zu, ret=%zd, len=%zu, copy_len=%zu\n", - ant_service.read_offset, consumed, ret, len, copy_len); - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - /* Can more data be put into the userspace buffer */ - if (ret == 0 && ant_service.read_offset >= ANT_HEADER_LENGTH && (len - consumed)) { - /* Calculate the amount of data that can be transferred */ - copy_len = min((td->length - ant_service.read_offset), (len - consumed)); - - /* Copy the data to the user buffer */ - ret = copy_to_user(&buf[consumed], &td->data[ant_service.read_offset], copy_len); - if (ret == 0) { - /* All good - Update our consumed information */ - ant_service.read_offset += copy_len; - consumed += copy_len; - - /* Have all data been copied to the userspace buffer */ - if (ant_service.read_offset == td->length) { - /* All good - read operation is completed */ - ant_service.read_offset = 0; - ant_service.read_operation = ANT_READ_OP_NONE; - } - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - SCSC_TAG_DEBUG(BT_H4, "read_offset=%zu, consumed=%zu, ret=%zd, len=%zu, copy_len=%zu\n", - ant_service.read_offset, consumed, ret, len, copy_len); - - return ret == 0 ? consumed : ret; -} - -static ssize_t scsc_ant_cmd_read(char __user *buf, size_t len) -{ - ssize_t ret = 0; - - /* Temp vars */ - if (ant_service.mailbox_cmd_ctr_driv_read != ant_service.mailbox_cmd_ctr_driv_write) { - struct ASMHCP_PROTOCOL *ap = ant_service.asmhcp_protocol; - struct ASMHCP_TD_CONTROL *td = &ap->cmd_controller_driver_transfer_ring - [ant_service.mailbox_cmd_ctr_driv_read]; - - ret = scsc_ant_copy_td_to_buffer(buf, len, td); - } - - return ret; -} - -static ssize_t scsc_ant_data_read(char __user *buf, size_t len) -{ - ssize_t ret = 0; - - if (ant_service.mailbox_data_ctr_driv_read != ant_service.mailbox_data_ctr_driv_write) { - struct ASMHCP_PROTOCOL *ap = ant_service.asmhcp_protocol; - struct ASMHCP_TD_CONTROL *td = &ap->data_controller_driver_transfer_ring - [ant_service.mailbox_data_ctr_driv_read]; - - ret = scsc_ant_copy_td_to_buffer(buf, len, td); - } - - return ret; -} - -static ssize_t scsc_bt_shm_ant_read_data(char __user *buf, size_t len) -{ - ssize_t ret = 0; - ssize_t consumed = 0; - - while (ant_service.read_operation == ANT_READ_OP_NONE && - ret == 0 && - ant_service.mailbox_data_ctr_driv_read != ant_service.mailbox_data_ctr_driv_write) { - /* Start a data copy to userspace */ - ant_service.read_operation = ANT_READ_OP_DATA; - ant_service.read_index = ant_service.mailbox_data_ctr_driv_read; - ret = scsc_ant_data_read(&buf[consumed], len - consumed); - if (ret > 0) { - /* All good - Update our consumed information */ - consumed += ret; - ret = 0; - - /* Update the index if all the data could be copied to the userspace buffer - * otherwise stop processing the data - */ - if (ant_service.read_operation == ANT_READ_OP_NONE) - BSMHCP_INCREASE_INDEX(ant_service.mailbox_data_ctr_driv_read, - ASMHCP_TRANSFER_RING_DATA_SIZE); - else - break; - } - } - - return ret == 0 ? consumed : ret; -} - -static ssize_t scsc_bt_shm_ant_read_cmd(char __user *buf, size_t len) -{ - ssize_t ret = 0; - ssize_t consumed = 0; - - while (ant_service.read_operation == ANT_READ_OP_NONE && - ret == 0 && - ant_service.mailbox_cmd_ctr_driv_read != ant_service.mailbox_cmd_ctr_driv_write) { - /* Start a cmd copy to userspace */ - ant_service.read_operation = ANT_READ_OP_CMD; - ant_service.read_index = ant_service.mailbox_cmd_ctr_driv_read; - ret = scsc_ant_cmd_read(&buf[consumed], len - consumed); - if (ret > 0) { - /* All good - Update our consumed information */ - consumed += ret; - ret = 0; - - /* Update the index if all the data could be copied to the userspace buffer - * otherwise stop processing the cmds - */ - if (ant_service.read_operation == ANT_READ_OP_NONE) - BSMHCP_INCREASE_INDEX(ant_service.mailbox_cmd_ctr_driv_read, - ASMHCP_TRANSFER_RING_CMD_SIZE); - else - break; - } - } - - return ret == 0 ? consumed : ret; -} - -static ssize_t scsc_shm_ant_read_continue(char __user *buf, size_t len) -{ - ssize_t ret = 0; - - /* Is a cmd read operation ongoing */ - if (ant_service.read_operation == ANT_READ_OP_CMD) { - SCSC_TAG_DEBUG(BT_H4, "ANT_READ_OP_CMD\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_ant_cmd_read(buf, len); - if (ant_service.read_operation == ANT_READ_OP_NONE) - /* All done - increase the read pointer and continue */ - if (ant_service.read_operation == ANT_READ_OP_NONE) - BSMHCP_INCREASE_INDEX(ant_service.mailbox_cmd_ctr_driv_read, - ASMHCP_TRANSFER_RING_CMD_SIZE); - /* Is a data read operation ongoing */ - } else if (ant_service.read_operation == ANT_READ_OP_DATA) { - SCSC_TAG_DEBUG(BT_H4, "ANT_READ_OP_DATA\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_ant_data_read(buf, len); - if (ant_service.read_operation == ANT_READ_OP_NONE) - /* All done - increase the read pointer and continue */ - BSMHCP_INCREASE_INDEX(ant_service.mailbox_data_ctr_driv_read, ASMHCP_TRANSFER_RING_DATA_SIZE); - } - - return ret; -} - -ssize_t scsc_shm_ant_read(struct file *file, char __user *buf, size_t len, loff_t *offset) -{ - ssize_t consumed = 0; - ssize_t ret = 0; - ssize_t res; - bool gen_bg_int = false; - - /* Only 1 reader is allowed */ - if (atomic_inc_return(&ant_service.ant_readers) != 1) { - atomic_dec(&ant_service.ant_readers); - return -EIO; - } - - /* Has en error been detect then just return with an error */ - if (atomic_read(&ant_service.error_count) != 0) { - atomic_dec(&ant_service.ant_readers); - return -EIO; - } - - /* Update the cached variables with the non-cached variables */ - ant_service.mailbox_cmd_ctr_driv_write = ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_write; - ant_service.mailbox_data_ctr_driv_write = ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_write; - - /* put the remaining data from the transfer ring into the available userspace buffer */ - if (ant_service.read_operation != ANT_READ_OP_NONE) { - ret = scsc_shm_ant_read_continue(buf, len); - /* Update the consumed variable in case a operation was ongoing */ - if (ret > 0) { - consumed = ret; - ret = 0; - } - } - - /* Main loop - Can only be entered when no operation is present on entering this function - * or no hardware error has been detected. It loops until data has been placed in the - * userspace buffer or an error has been detected - */ - while (atomic_read(&ant_service.error_count) == 0 && consumed == 0) { - /* Does any of the read/write pairs differs */ - if (ant_service.mailbox_data_ctr_driv_read == ant_service.mailbox_data_ctr_driv_write && - ant_service.mailbox_cmd_ctr_driv_read == ant_service.mailbox_cmd_ctr_driv_write && - atomic_read(&ant_service.error_count) == 0 && - ant_service.asmhcp_protocol->header.panic_deathbed_confession == 0) { - /* Don't wait if in NONBLOCK mode */ - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - /* All read/write pairs are identical - wait for the firmware. The conditional - * check is used to verify that a read/write pair has actually changed - */ - ret = wait_event_interruptible(bt_service.read_wait, - (ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_write != - ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_read || - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_write != - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_read || - atomic_read(&ant_service.error_count) != 0 || - ant_service.asmhcp_protocol->header.panic_deathbed_confession)); - - /* Has an error been detected elsewhere in the driver then just return from this function */ - if (atomic_read(&ant_service.error_count) != 0) - break; - - /* Any failures is handled by the userspace application */ - if (ret) - break; - - /* Refresh our write indexes before starting to process the protocol */ - ant_service.mailbox_cmd_ctr_driv_write = - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_write; - ant_service.mailbox_data_ctr_driv_write = - ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_write; - } - - /* First: process any pending cmd that needs to be sent to userspace */ - res = scsc_bt_shm_ant_read_cmd(&buf[consumed], len - consumed); - if (res > 0) - consumed += res; - else - ret = res; - - /* Second: process any pending data that needs to be sent to userspace */ - res = scsc_bt_shm_ant_read_data(&buf[consumed], len - consumed); - if (res > 0) - consumed += res; - else - ret = res; - } - - /* If anything was read, generate the appropriate interrupt(s) */ - if (ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_read != ant_service.mailbox_cmd_ctr_driv_read || - ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_read != ant_service.mailbox_data_ctr_driv_read) - gen_bg_int = true; - - /* Update the read index for all transfer rings */ - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_read = ant_service.mailbox_cmd_ctr_driv_read; - ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_read = ant_service.mailbox_data_ctr_driv_read; - - /* Ensure the data is updating correctly in memory */ - mmiowb(); - - if (gen_bg_int) - scsc_service_mifintrbit_bit_set(ant_service.service, - ant_service.asmhcp_protocol->header.ap_to_bg_int_src, - SCSC_MIFINTR_TARGET_R4); - - /* Decrease the ant readers counter */ - atomic_dec(&ant_service.ant_readers); - - return ret == 0 ? consumed : ret; -} - -ssize_t scsc_shm_ant_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) -{ - size_t length; - size_t ant_pkt_len; - ssize_t written = 0; - ssize_t ret = 0; - size_t pkt_count = 0; - - SCSC_TAG_DEBUG(BT_H4, "enter\n"); - - UNUSED(file); - UNUSED(offset); - - /* Only 1 writer is allowed */ - if (atomic_inc_return(&ant_service.ant_writers) != 1) { - SCSC_TAG_DEBUG(BT_H4, "only one reader allowed\n"); - atomic_dec(&ant_service.ant_writers); - return -EIO; - } - - /* Has en error been detect then just return with an error */ - if (atomic_read(&ant_service.error_count) != 0) { - SCSC_TAG_DEBUG(BT_H4, "error has occured\n"); - atomic_dec(&ant_service.ant_writers); - return -EIO; - } - - while (written != count && ret == 0) { - length = min(count - written, sizeof(ant_write_buffer) - ant_service.ant_write_offset); - SCSC_TAG_DEBUG(BT_H4, "count: %zu, length: %zu, ant_write_offset: %zu, written:%zu, size:%zu\n", - count, length, ant_service.ant_write_offset, - written - (pkt_count * 2), sizeof(ant_write_buffer)); - - /* Is there room in the temp buffer */ - if (length == 0) { - SCSC_TAG_ERR(BT_H4, "no room in the buffer\n"); - atomic_inc(&ant_service.error_count); - ret = -EIO; - break; - } - - /* Copy the userspace data to the target buffer */ - ret = copy_from_user(&ant_write_buffer[ant_service.ant_write_offset], &buf[written], length); - - if (ret == 0) { - /* Is the message a data message? */ - if (ant_write_buffer[0] == ANT_DATA_MSG) { - /* Extract the data packet length */ - ant_pkt_len = ant_write_buffer[1] + ANT_HEADER_LENGTH + 1; - - /* Is it a complete packet available */ - if (ant_pkt_len <= (length + ant_service.ant_write_offset)) { - /* Transfer the packet to the ANT data transfer ring */ - ret = scsc_shm_ant_data_write(&ant_write_buffer[2], ant_pkt_len - 2); - if (ret >= 0) { - written += (ant_pkt_len - ant_service.ant_write_offset); - pkt_count += 1; - ant_service.ant_write_offset = 0; - ret = 0; - } - } else { - /* Still needing data to have the complete packet */ - SCSC_TAG_WARNING(BT_H4, - "missing data (need=%zu, got=%zu)\n", - ant_pkt_len, (length - ant_service.ant_write_offset)); - written += length; - ant_service.ant_write_offset += (u32) length; - } - /* Is the message a command message? */ - } else if (ant_write_buffer[0] == ANT_COMMAND_MSG) { - /* Extract the ANT command packet length */ - ant_pkt_len = ant_write_buffer[1] + ANT_HEADER_LENGTH + 1; - - /* Is it a complete packet available */ - if ((ant_pkt_len) <= (length + ant_service.ant_write_offset)) { - /* Transfer the packet to the ANT command transfer ring */ - ret = scsc_shm_ant_cmd_write(&ant_write_buffer[2], ant_pkt_len - 2); - if (ret >= 0) { - written += (ant_pkt_len - ant_service.ant_write_offset); - pkt_count += 1; - ant_service.ant_write_offset = 0; - ret = 0; - } - } else { - /* Still needing data to have the complete packet */ - SCSC_TAG_WARNING(BT_H4, - "missing data (need=%zu, got=%zu)\n", - (ant_pkt_len), (length + ant_service.ant_write_offset)); - written += length; - ant_service.ant_write_offset += (u32) length; - } - /* Is there less data than a header then just wait for more */ - } else if (length <= ANT_HEADER_LENGTH) { - ant_service.ant_write_offset += length; - written += length; - /* Header is unknown - unable to proceed */ - } else { - atomic_inc(&ant_service.error_count); - ret = -EIO; - } - } else { - SCSC_TAG_WARNING(BT_H4, "copy_from_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - SCSC_TAG_DEBUG(BT_H4, "ant_write_offset=%zu, ret=%zu, written=%zu\n", - ant_service.ant_write_offset, ret, written - (pkt_count * 2)); - - /* Decrease the ant readers counter */ - atomic_dec(&ant_service.ant_writers); - - return ret == 0 ? written : ret; -} - -unsigned int scsc_shm_ant_poll(struct file *file, poll_table *wait) -{ - /* Add the wait queue to the polling queue */ - poll_wait(file, &ant_service.read_wait, wait); - - if (atomic_read(&ant_service.error_count) != 0) - return POLLERR; - - /* Has en error been detect then just return with an error */ - if (ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_write != - ant_service.asmhcp_protocol->header.mailbox_data_ctr_driv_read || - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_write != - ant_service.asmhcp_protocol->header.mailbox_cmd_ctr_driv_read) { - SCSC_TAG_DEBUG(BT_H4, "queue(s) changed\n"); - return POLLIN | POLLRDNORM; /* readeable */ - } - - SCSC_TAG_DEBUG(BT_H4, "no change\n"); - - return (atomic_read(&ant_service.error_count) != 0) ? POLLERR : POLLOUT; -} - -/* Initialise the shared memory interface for ANT */ -int scsc_ant_shm_init(void) -{ - /* Get kmem pointer to the shared memory ref */ - ant_service.asmhcp_protocol = scsc_mx_service_mif_addr_to_ptr(ant_service.service, ant_service.asmhcp_ref); - if (ant_service.asmhcp_protocol == NULL) { - SCSC_TAG_ERR(BT_COMMON, "couldn't map kmem to shm_ref 0x%08x\n", (u32)ant_service.asmhcp_ref); - return -ENOMEM; - } - - /* Clear the protocol shared memory area */ - memset(ant_service.asmhcp_protocol, 0, sizeof(*ant_service.asmhcp_protocol)); - ant_service.asmhcp_protocol->header.magic_value = ASMHCP_PROTOCOL_MAGICVALUE; - ant_service.mailbox_data_ctr_driv_read = 0; - ant_service.mailbox_data_ctr_driv_write = 0; - ant_service.mailbox_cmd_ctr_driv_read = 0; - ant_service.mailbox_cmd_ctr_driv_write = 0; - ant_service.read_index = 0; - - /* Initialise the interrupt handlers */ - scsc_ant_shm_init_interrupt(); - - return 0; -} - -/* Terminate the shared memory interface for ANT, stopping its thread. - * - * Note: The service must be stopped prior to calling this function. - * The shared memory can only be released after calling this function. - */ -void scsc_ant_shm_exit(void) -{ - /* Release IRQs */ - if (ant_service.asmhcp_protocol != NULL) { - scsc_service_mifintrbit_unregister_tohost( - ant_service.service, - ant_service.asmhcp_protocol->header.bg_to_ap_int_src); - - scsc_service_mifintrbit_free_fromhost( - ant_service.service, - ant_service.asmhcp_protocol->header.ap_to_bg_int_src, - SCSC_MIFINTR_TARGET_R4); - } - - /* Clear all control structures */ - ant_service.asmhcp_protocol = NULL; -} diff --git a/drivers/misc/samsung/scsc_bt/scsc_avdtp_detect.c b/drivers/misc/samsung/scsc_bt/scsc_avdtp_detect.c deleted file mode 100644 index c7418efd1f57..000000000000 --- a/drivers/misc/samsung/scsc_bt/scsc_avdtp_detect.c +++ /dev/null @@ -1,807 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2015 Samsung Electronics Co., Ltd - * - ****************************************************************************/ - -/* Before submitting new changes to this file please make sure to run the module tests to verify - * that the change didn't break anything. Also, make sure to write new tests that captures the - * change. The module tests can be found in "vendor/samsung_slsi/scsc_tools/kernel_unit_test/" - * from where there are run with "make". If needed its git project nane is: - * "Connectivity/Android/platform/vendor/samsung_slsi/scsc_tools/kernel_unit_test" */ - -/* MX BT shared memory interface */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "scsc_bt_priv.h" -#include "scsc_shm.h" -/** - * Coex AVDTP detection. - * - * Strategy: - * - * - On the L2CAP signaling CID, look for connect requests with the AVDTP PSM - * - * - Assume the first AVDTP connection is the signaling channel. - * (AVDTP 1.3, section 5.4.6 "Transport and Signaling Channel Establishment") - * - * - If a signaling channel exists, assume the next connection is the streaming channel - * - * - If a streaming channel exists, look for AVDTP start, suspend, abort and close signals - * -- When one of these is found, signal the FW with updated acl_id and cid - * - * - If the ACL is torn down, make sure to clean up. - * - * */ - -#define IS_VALID_CID_CONN_RESP(is_tx, avdtp, data) ((is_tx && avdtp->dst_cid == HCI_L2CAP_SOURCE_CID(data)) || \ - (!is_tx && avdtp->src_cid == HCI_L2CAP_SOURCE_CID(data))) - - -#define IS_VALID_CID_DISCONNECT_REQ(is_tx, avdtp, data) ((is_tx && avdtp.src_cid == HCI_L2CAP_SOURCE_CID(data) && \ - avdtp.dst_cid == HCI_L2CAP_RSP_DEST_CID(data)) || \ - (!is_tx && avdtp.src_cid == HCI_L2CAP_RSP_DEST_CID(data) && \ - avdtp.dst_cid == HCI_L2CAP_SOURCE_CID(data))) - -#define STORE_DETECTED_CID_CONN_REQ(is_tx, avdtp, data) \ - do { \ - if (is_tx) { \ - avdtp->src_cid = HCI_L2CAP_SOURCE_CID(data); \ - } else { \ - avdtp->dst_cid = HCI_L2CAP_SOURCE_CID(data); \ - } \ - } while (0) - -#define STORE_DETECTED_CID_CONN_RESP(is_tx, avdtp, data) \ - do { \ - if (is_tx) { \ - avdtp->src_cid = HCI_L2CAP_RSP_DEST_CID(data); \ - } else { \ - avdtp->dst_cid = HCI_L2CAP_RSP_DEST_CID(data); \ - } \ - } while (0) - -#ifdef ENABLE_MODULE_TESTS_DEBUG -#undef SCSC_TAG_DEBUG -#define SCSC_TAG_DEBUG(tag, fmt, ...) \ - fprintf(stdout, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__) -#endif - -/* Forward declarations */ -void scsc_avdtp_detect_reset(struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci, - bool reset_signal, - bool reset_signal_ongoing, - bool reset_stream, - bool reset_stream_ongoing, - bool reset_local_seids, - bool reset_remote_seids); - -/* Simple list traversal to find an existing AVDTP detection from a hci connection handle. If - * not found, the function returns NULL - */ -static struct scsc_bt_avdtp_detect_hci_connection *scsc_avdtp_detect_search_hci_connection( - u16 hci_connection_handle) -{ - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci; - - avdtp_hci = bt_service.avdtp_detect.connections; - while (avdtp_hci) { - if (avdtp_hci->hci_connection_handle == hci_connection_handle) { - /* Found it */ - break; - } - avdtp_hci = avdtp_hci->next; - } - return avdtp_hci; -} - -/* Find existing detection for a given connection handle. If provided as argument, a new detection - * will be created if it doesn't exist. The returned element is locked and must be unlocked before - * moving to another context. - */ -static struct scsc_bt_avdtp_detect_hci_connection *scsc_avdtp_detect_find_or_create_hci_connection( - u16 hci_connection_handle, - bool create) -{ - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci; - - spin_lock(&bt_service.avdtp_detect.lock); - - avdtp_hci = scsc_avdtp_detect_search_hci_connection(hci_connection_handle); - if (avdtp_hci) - spin_lock(&avdtp_hci->lock); - - /* Unlock the list again and check if a new element must be created. If that is the case, - * malloc the new memory and lock the list afterwards such that others are not spinning for - * some undefined amount of time. The trade-off in this construction is that the memory - * potentially is allocated twice in rare situations, and the list must therefore be locked - * and searched again before inserting. - */ - spin_unlock(&bt_service.avdtp_detect.lock); - - /* Check if the existing detection was found. If not create it */ - if (!avdtp_hci && create) { - avdtp_hci = kmalloc(sizeof(struct scsc_bt_avdtp_detect_hci_connection), GFP_KERNEL); - if (avdtp_hci) { - struct scsc_bt_avdtp_detect_hci_connection *head; - struct scsc_bt_avdtp_detect_hci_connection *recheck_avdtp_hci; - - memset(avdtp_hci, 0, sizeof(struct scsc_bt_avdtp_detect_hci_connection)); - avdtp_hci->signal.type = BT_AVDTP_CONN_TYPE_SIGNAL; - avdtp_hci->stream.type = BT_AVDTP_CONN_TYPE_STREAM; - avdtp_hci->ongoing.incoming_signal.type = BT_AVDTP_CONN_TYPE_SIGNAL; - avdtp_hci->ongoing.outgoing_signal.type = BT_AVDTP_CONN_TYPE_SIGNAL; - avdtp_hci->ongoing.incoming_stream.type = BT_AVDTP_CONN_TYPE_STREAM; - avdtp_hci->ongoing.outgoing_stream.type = BT_AVDTP_CONN_TYPE_STREAM; - avdtp_hci->signal.state = BT_AVDTP_STATE_IDLE_SIGNALING; - avdtp_hci->signal.src_cid = 0; - avdtp_hci->signal.dst_cid = 0; - avdtp_hci->hci_connection_handle = hci_connection_handle; - scsc_avdtp_detect_reset(avdtp_hci, false, true, true, true, true, true); - - /* The element is ready for insertion into the list. Recheck the list to make sure that - * the hci handle hasn't been detected meanwhile. - */ - spin_lock(&bt_service.avdtp_detect.lock); - - recheck_avdtp_hci = scsc_avdtp_detect_search_hci_connection(hci_connection_handle); - if (recheck_avdtp_hci == NULL) { - /* Insert into list */ - spin_lock_init(&avdtp_hci->lock); - spin_lock(&avdtp_hci->lock); - head = bt_service.avdtp_detect.connections; - bt_service.avdtp_detect.connections = avdtp_hci; - avdtp_hci->next = head; - spin_unlock(&bt_service.avdtp_detect.lock); - } else { - /* The element was already present. Free the allocated memory and return the found - * element. - */ - spin_lock(&recheck_avdtp_hci->lock); - spin_unlock(&bt_service.avdtp_detect.lock); - kfree(avdtp_hci); - avdtp_hci = NULL; - avdtp_hci = recheck_avdtp_hci; - } - } - } - return avdtp_hci; -} - -/* Find an existing l2cap connection struct. Works for both signal and stream since their internal - * structures are equal */ -static struct scsc_bt_avdtp_detect_connection *scsc_avdtp_detect_find_l2cap_connection(struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci, - enum scsc_bt_avdtp_detect_conn_req_direction_enum direction) -{ - struct scsc_bt_avdtp_detect_connection *avdtp_l2cap = NULL; - - /* Return either signal or stream l2cap connection */ - if (avdtp_hci) { - /* Check if there is already a signal connection and return the ongoing stream */ - if (avdtp_hci->signal.state == BT_AVDTP_STATE_COMPLETE_SIGNALING) { - if (direction == BT_AVDTP_CONN_REQ_DIR_OUTGOING) - avdtp_l2cap = &avdtp_hci->ongoing.outgoing_stream; - else - avdtp_l2cap = &avdtp_hci->ongoing.incoming_stream; - } else { - /* If not, use the ongoing signal */ - if (direction == BT_AVDTP_CONN_REQ_DIR_OUTGOING) - avdtp_l2cap = &avdtp_hci->ongoing.outgoing_signal; - else - avdtp_l2cap = &avdtp_hci->ongoing.incoming_signal; - } - } - return avdtp_l2cap; -} - -/* Handle CONNECTION_REQUEST and detect signal or stream connections. The function handles both RX and TX, where - * connect requests in TX direction is mapped to "outgoing". RX direction is mapped to "incoming" */ -static void scsc_bt_avdtp_detect_connection_conn_req_handling(uint16_t hci_connection_handle, - const unsigned char *data, - uint16_t length, - bool is_tx) -{ - struct scsc_bt_avdtp_detect_connection *avdtp_l2cap = NULL; - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci = NULL; - - /* Ignore everything else than the PSM */ - if (HCI_L2CAP_CON_REQ_PSM(data) == L2CAP_AVDTP_PSM) { - // Check if there is already an detection for the given hci handle - avdtp_hci = scsc_avdtp_detect_find_or_create_hci_connection( - hci_connection_handle, - true); - - avdtp_l2cap = scsc_avdtp_detect_find_l2cap_connection(avdtp_hci, - is_tx ? BT_AVDTP_CONN_REQ_DIR_OUTGOING : BT_AVDTP_CONN_REQ_DIR_INCOMING); - - if (avdtp_hci && avdtp_l2cap) { - if (avdtp_l2cap->state == BT_AVDTP_STATE_IDLE_SIGNALING) { - - /* AVDTP signal channel was detected - store dst_cid or src_cid depending on the transmit - * direction, and store the connection_handle. */ - STORE_DETECTED_CID_CONN_REQ(is_tx, avdtp_l2cap, data); - avdtp_l2cap->state = BT_AVDTP_STATE_PENDING_SIGNALING; - SCSC_TAG_DEBUG(BT_H4, "Signaling dst CID: 0x%04X, src CID: 0x%04X, aclid: 0x%04X (tx=%u)\n", - avdtp_l2cap->dst_cid, - avdtp_l2cap->src_cid, - avdtp_hci->hci_connection_handle, - is_tx); - } else if (avdtp_l2cap->state == BT_AVDTP_STATE_IDLE_STREAMING && - avdtp_hci->signal.state == BT_AVDTP_STATE_COMPLETE_SIGNALING) { - - /* AVDTP stream channel was detected - store dst_cid or src_cid depending on the transmit - * direction. */ - STORE_DETECTED_CID_CONN_REQ(is_tx, avdtp_l2cap, data); - avdtp_l2cap->state = BT_AVDTP_STATE_PENDING_STREAMING; - SCSC_TAG_DEBUG(BT_H4, "Streaming dst CID: 0x%04X, src CID: 0x%04X, aclid: 0x%04X (%u)\n", - avdtp_l2cap->dst_cid, - avdtp_l2cap->src_cid, - avdtp_hci->hci_connection_handle, - is_tx); - } - } - if (avdtp_hci) - spin_unlock(&avdtp_hci->lock); - } -} - -/* Handle CONNECTION_REPSONS and detect signal or stream connections. The function handles both RX and TX, where - * connect requests in TX direction is mapped to "incoming". RX direction is mapped to "outgoing" */ -static void scsc_bt_avdtp_detect_connection_conn_resp_handling(uint16_t hci_connection_handle, - const unsigned char *data, - uint16_t length, - bool is_tx) -{ - - /* Check if there is already a signal connection */ - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci = - scsc_avdtp_detect_find_or_create_hci_connection(hci_connection_handle, false); - struct scsc_bt_avdtp_detect_connection *avdtp_l2cap = - scsc_avdtp_detect_find_l2cap_connection(avdtp_hci, - is_tx ? BT_AVDTP_CONN_REQ_DIR_INCOMING : BT_AVDTP_CONN_REQ_DIR_OUTGOING); - /* Only consider RSP on expected connection handle */ - if (avdtp_hci && avdtp_l2cap) { - if (HCI_L2CAP_CON_RSP_RESULT(data) == HCI_L2CAP_CON_RSP_RESULT_SUCCESS) { - if (IS_VALID_CID_CONN_RESP(is_tx, avdtp_l2cap, data) && - avdtp_l2cap->state == BT_AVDTP_STATE_PENDING_SIGNALING) { - - /* If we were waiting to complete an AVDTP signal detection - store the dst_cid or src_cid depending - * on the transmit direction */ - STORE_DETECTED_CID_CONN_RESP(is_tx, avdtp_l2cap, data); - avdtp_l2cap->state = BT_AVDTP_STATE_COMPLETE_SIGNALING; - - /* Switch to use "signal" and delete "ongoing" since the AVDTP signaling has now been - * detected */ - avdtp_hci->signal = *avdtp_l2cap; - scsc_avdtp_detect_reset(avdtp_hci, false, true, false, false, false, false); - SCSC_TAG_DEBUG(BT_H4, "Signaling dst CID: 0x%04X, src CID: 0x%04X, aclid: 0x%04X (tx=%u)\n", - avdtp_hci->signal.dst_cid, - avdtp_hci->signal.src_cid, - avdtp_hci->hci_connection_handle, - is_tx); - - } else if (IS_VALID_CID_CONN_RESP(is_tx, avdtp_l2cap, data) && - avdtp_l2cap->state == BT_AVDTP_STATE_PENDING_STREAMING) { - - /* If we were waiting to complete an AVDTP stream detection - store the dst_cid or src_cid depending - * on the transmit direction */ - STORE_DETECTED_CID_CONN_RESP(is_tx, avdtp_l2cap, data); - avdtp_l2cap->state = BT_AVDTP_STATE_COMPLETE_STREAMING; - - /* Switch to use "stream". If both an incoming and outgoing connection response was "expected" - * the first one wins. */ - avdtp_hci->stream = *avdtp_l2cap; - scsc_avdtp_detect_reset(avdtp_hci, false, false, false, true, false, false); - - SCSC_TAG_DEBUG(BT_H4, "Streaming dst CID: 0x%04X, src CID: 0x%04X, aclid: 0x%04X (tx=%u)\n", - avdtp_hci->stream.dst_cid, - avdtp_hci->stream.src_cid, - avdtp_hci->hci_connection_handle, - is_tx); - } - } else if (HCI_L2CAP_CON_RSP_RESULT(data) >= HCI_L2CAP_CON_RSP_RESULT_REFUSED) { - /* In case of a CONN_REFUSED the existing CIDs must be cleaned up such that the detection is ready - * for a new connection request */ - if (IS_VALID_CID_CONN_RESP(is_tx, avdtp_l2cap, data) && - avdtp_l2cap->state == BT_AVDTP_STATE_PENDING_SIGNALING) { - avdtp_l2cap->dst_cid = avdtp_l2cap->src_cid = 0; - avdtp_l2cap->state = BT_AVDTP_STATE_IDLE_SIGNALING; - - } else if (IS_VALID_CID_CONN_RESP(is_tx, avdtp_l2cap, data) && - avdtp_l2cap->state == BT_AVDTP_STATE_PENDING_STREAMING) { - - /* Connection refused on streaming connect request. Reset dst_cid and src_cid, and - * reset the state to IDLE such that new connection requests can be detected */ - avdtp_l2cap->dst_cid = avdtp_l2cap->src_cid = 0; - avdtp_l2cap->state = BT_AVDTP_STATE_IDLE_STREAMING; - - } - } - } - if (avdtp_hci) - spin_unlock(&avdtp_hci->lock); -} - -/* Handle DISCONNECT_REQUEST and remove all current detections on the specific CIDs */ -static bool scsc_bt_avdtp_detect_connection_disconnect_req_handling(uint16_t hci_connection_handle, - const unsigned char *data, - uint16_t length, - bool is_tx) -{ - bool result = false; - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci = - scsc_avdtp_detect_find_or_create_hci_connection(hci_connection_handle, false); - - if (avdtp_hci) { - if (avdtp_hci->signal.state == BT_AVDTP_STATE_COMPLETE_SIGNALING && - IS_VALID_CID_DISCONNECT_REQ(is_tx, avdtp_hci->signal, data)) { - - /* Disconnect the current registered signaling and streaming AVDTP connection */ - scsc_avdtp_detect_reset(avdtp_hci, true, true, true, true, true, true); - - /* The detection was removed and it can therefore not be unlocked */ - avdtp_hci = NULL; - - SCSC_TAG_DEBUG(BT_H4, "Signaling src CID disconnected (aclid: 0x%04X) (TX=%u)\n", - hci_connection_handle, - is_tx); - } else if (avdtp_hci->stream.state == BT_AVDTP_STATE_COMPLETE_STREAMING && - IS_VALID_CID_DISCONNECT_REQ(is_tx, avdtp_hci->stream, data)) { - - /* Disconnect the current registered streaming AVDTP connection */ - scsc_avdtp_detect_reset(avdtp_hci, false, false, true, true, false, false); - - SCSC_TAG_DEBUG(BT_H4, "Streaming src CID disconnected (aclid: 0x%04X) (TX=%u)\n", - hci_connection_handle, - is_tx); - result = true; - } - if (avdtp_hci) - spin_unlock(&avdtp_hci->lock); - } - return result; -} - -/* Detects if there is any of the L2CAP codes of interrest, and returns true of the FW should be signalled a change */ -static bool scsc_bt_avdtp_detect_connection_rxtx(uint16_t hci_connection_handle, const unsigned char *data, uint16_t length, bool is_tx) -{ - uint8_t code = 0; - if (length < AVDTP_DETECT_MIN_DATA_LENGTH) { - SCSC_TAG_DEBUG(BT_H4, "Ignoring L2CAP signal, length %u)\n", length); - return false; - } - - code = HCI_L2CAP_CODE(data); - switch (code) { - - case L2CAP_CODE_CONNECT_REQ: - { - /* Handle connection request */ - scsc_bt_avdtp_detect_connection_conn_req_handling(hci_connection_handle, data, length, is_tx); - break; - } - case L2CAP_CODE_CONNECT_RSP: - { - if (length < AVDTP_DETECT_MIN_DATA_LENGTH_CON_RSP) { - SCSC_TAG_WARNING(BT_H4, "Ignoring L2CAP CON RSP in short packet, length %u)\n", length); - return false; - } - /* Handle connection response */ - scsc_bt_avdtp_detect_connection_conn_resp_handling(hci_connection_handle, data, length, is_tx); - break; - } - case L2CAP_CODE_DISCONNECT_REQ: - { - /* Handle disconnect request */ - return scsc_bt_avdtp_detect_connection_disconnect_req_handling(hci_connection_handle, data, length, is_tx); - break; - } - default: - break; - } - return false; -} - -/* Check if there are any SEIDs from the discover that are SINK, and store them as SINK candidates */ -static void scsc_avdtp_detect_check_discover_for_snk_seids(uint16_t hci_connection_handle, - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci, - const unsigned char *data, - uint16_t length, - bool is_tx) -{ - uint16_t i = 0; - uint16_t n_seid_info = (length - HCI_L2CAP_CONF_SEID_OFFSET) / HCI_L2CAP_CONF_SEID_INFO_SIZE; - struct scsc_bt_avdtp_detect_snk_seid *seid = NULL; - - /* Remove potential existing SEID infos on the either local or remote */ - scsc_avdtp_detect_reset(avdtp_hci, false, false, false, false, is_tx, !is_tx); - for (i = 0; i < n_seid_info; i++) { - /* Only consider SEID if it's type is SINK. This means that for TX, look for TSEP equal to SNK. - * For RX look for TSEP equal to SRC, since this would result in our side being SNK */ - if ((is_tx && HCI_L2CAP_CONF_TSEP(data, i) == HCI_L2CAP_CONF_TSEP_SNK) || - (!is_tx && HCI_L2CAP_CONF_TSEP(data, i) == HCI_L2CAP_CONF_TSEP_SRC)) { - - if (avdtp_hci) - spin_unlock(&avdtp_hci->lock); - - seid = kmalloc(sizeof(struct scsc_bt_avdtp_detect_snk_seid), GFP_KERNEL); - - avdtp_hci = scsc_avdtp_detect_find_or_create_hci_connection(hci_connection_handle, - false); - - if (avdtp_hci && seid) { - memset(seid, 0, sizeof(struct scsc_bt_avdtp_detect_snk_seid)); - seid->seid = HCI_L2CAP_CONF_SEID(data, i); - SCSC_TAG_DEBUG(BT_H4, "Storing seid=%u as candidate for SINK, aclid: 0x%04X\n", - seid->seid, - avdtp_hci->hci_connection_handle); - /* Store the information on either local or remote */ - if (is_tx) { - if (avdtp_hci->tsep_detect.local_snk_seids) - seid->next = avdtp_hci->tsep_detect.local_snk_seids; - avdtp_hci->tsep_detect.local_snk_seids = seid; - } else { - if (avdtp_hci->tsep_detect.remote_snk_seids) - seid->next = avdtp_hci->tsep_detect.remote_snk_seids; - avdtp_hci->tsep_detect.remote_snk_seids = seid; - } - } else - kfree(seid); - } - } -} - -/* Check if the set configuration matches any of the SINK candidates */ -static void scsc_avdtp_detect_match_set_conf_seid_with_discover(struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci, - const unsigned char *data, - bool is_tx) -{ - struct scsc_bt_avdtp_detect_snk_seid *seid_info; - uint8_t candidate = 0; - - /* Default to SRC */ - avdtp_hci->tsep_detect.tsep = BT_AVDTP_TSEP_SRC; - - if (is_tx) { - seid_info = avdtp_hci->tsep_detect.local_snk_seids; - candidate = avdtp_hci->tsep_detect.local_snk_seid_candidate; - } else { - seid_info = avdtp_hci->tsep_detect.remote_snk_seids; - candidate = avdtp_hci->tsep_detect.remote_snk_seid_candidate; - } - - while (seid_info) { - if (seid_info->seid == candidate) { - /* SINK was detected */ - avdtp_hci->tsep_detect.tsep = BT_AVDTP_TSEP_SNK; - break; - } - seid_info = seid_info->next; - } - /* Clear the canditate SEID since it has now been checked */ - avdtp_hci->tsep_detect.local_snk_seid_candidate = 0; - avdtp_hci->tsep_detect.remote_snk_seid_candidate = 0; - SCSC_TAG_DEBUG(BT_H4, "TSEP for active stream, snk=%d, aclid=0x%04X\n", - avdtp_hci->tsep_detect.tsep, - avdtp_hci->hci_connection_handle); -} - -/* Detects if the AVDTP signal leads to a state change that the FW should know */ -static uint8_t scsc_avdtp_detect_signaling_rxtx(uint16_t hci_connection_handle, - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci, - const unsigned char *data, - uint16_t length, - bool is_tx) -{ - u8 signal_id = AVDTP_SIGNAL_ID(data); - u8 message_type = AVDTP_MESSAGE_TYPE(data); - - SCSC_TAG_DEBUG(BT_H4, "id: 0x%02X, type: 0x%02X)\n", signal_id, message_type); - - if (message_type == AVDTP_MESSAGE_TYPE_RSP_ACCEPT) { - if (signal_id == AVDTP_SIGNAL_ID_START) - return AVDTP_DETECT_SIGNALING_ACTIVE; - else if (signal_id == AVDTP_SIGNAL_ID_OPEN) - return AVDTP_DETECT_SIGNALING_OPEN; - else if (signal_id == AVDTP_SIGNAL_ID_CLOSE || signal_id == AVDTP_SIGNAL_ID_SUSPEND || - signal_id == AVDTP_SIGNAL_ID_ABORT) - return AVDTP_DETECT_SIGNALING_INACTIVE; - else if (signal_id == AVDTP_SIGNAL_ID_DISCOVER) { - /* Check the discover signal for potential SNK candidate SEIDs */ - scsc_avdtp_detect_check_discover_for_snk_seids(hci_connection_handle, - avdtp_hci, data, length, is_tx); - } else if (signal_id == AVDTP_SIGNAL_ID_SET_CONF) { - /* Check if the SEID from set config matches a SNK SEID */ - scsc_avdtp_detect_match_set_conf_seid_with_discover(avdtp_hci, data, is_tx); - } - } else if (message_type == AVDTP_MESSAGE_TYPE_CMD) { - if (signal_id == AVDTP_SIGNAL_ID_SET_CONF) { - if (is_tx) - avdtp_hci->tsep_detect.remote_snk_seid_candidate = HCI_L2CAP_SET_CONF_ACP_SEID(data); - else - avdtp_hci->tsep_detect.local_snk_seid_candidate = HCI_L2CAP_SET_CONF_ACP_SEID(data); - SCSC_TAG_DEBUG(BT_H4, "Set configuration was detected; local_seid_candidate=%u, remote_seid_candidate=%u (aclid: 0x%04X)\n", - avdtp_hci->tsep_detect.local_snk_seid_candidate, - avdtp_hci->tsep_detect.remote_snk_seid_candidate, - avdtp_hci->hci_connection_handle); - } - } else if (message_type == AVDTP_MESSAGE_TYPE_GENERAL_REJECT || message_type == AVDTP_MESSAGE_TYPE_RSP_REJECT) { - if (signal_id == AVDTP_SIGNAL_ID_SET_CONF) { - if (is_tx) { - if (avdtp_hci->tsep_detect.local_snk_seid_candidate) - avdtp_hci->tsep_detect.local_snk_seid_candidate = 0; - } else { - if (avdtp_hci->tsep_detect.remote_snk_seid_candidate) - avdtp_hci->tsep_detect.remote_snk_seid_candidate = 0; - } - } - } - return AVDTP_DETECT_SIGNALING_IGNORE; -} - -/* Public function that hooks into scsc_shm.c. It pass the provided data on the proper functions such that - * the AVDTP can be detected. If any state change is detected, the FW is signalled */ -void scsc_avdtp_detect_rxtx(u16 hci_connection_handle, const unsigned char *data, uint16_t length, bool is_tx) -{ - /* Look for AVDTP connections */ - bool avdtp_gen_bg_int = false; - uint16_t cid_to_fw = 0; - bool is_sink = false; - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci = NULL; - bool avdtp_open = false; - - /* Look for AVDTP connections */ - if (HCI_L2CAP_RX_CID((const unsigned char *)(data)) == L2CAP_SIGNALING_CID) { - if (scsc_bt_avdtp_detect_connection_rxtx(hci_connection_handle, data, length, is_tx)) { - avdtp_gen_bg_int = true; - - avdtp_hci = scsc_avdtp_detect_find_or_create_hci_connection( - hci_connection_handle, - false); - - if (avdtp_hci) { - cid_to_fw = avdtp_hci->stream.dst_cid; - is_sink = avdtp_hci->tsep_detect.tsep == BT_AVDTP_TSEP_SNK; - } - } - } else { - /* Check if we have detected any signal on the connection handle */ - avdtp_hci = scsc_avdtp_detect_find_or_create_hci_connection( - hci_connection_handle, - false); - - if (avdtp_hci) { - if (avdtp_hci->signal.state == BT_AVDTP_STATE_COMPLETE_SIGNALING && - length >= AVDTP_DETECT_MIN_AVDTP_LENGTH && - ((is_tx && avdtp_hci->signal.dst_cid != 0 && - avdtp_hci->signal.dst_cid == HCI_L2CAP_RX_CID((const unsigned char *)(data))) || - (!is_tx && avdtp_hci->signal.src_cid != 0 && - avdtp_hci->signal.src_cid == HCI_L2CAP_RX_CID((const unsigned char *)(data))))) { - /* Signaling has been detected on the given CID and hci_connection_handle */ - uint8_t result = scsc_avdtp_detect_signaling_rxtx(hci_connection_handle, - avdtp_hci, data, length, is_tx); - - if (result != AVDTP_DETECT_SIGNALING_IGNORE) { - avdtp_gen_bg_int = true; - if (result != AVDTP_DETECT_SIGNALING_INACTIVE) - cid_to_fw = avdtp_hci->stream.dst_cid; - if (result == AVDTP_DETECT_SIGNALING_OPEN) - avdtp_open = true; - is_sink = avdtp_hci->tsep_detect.tsep == BT_AVDTP_TSEP_SNK; - } - - } - } - } - - if (avdtp_hci) - spin_unlock(&avdtp_hci->lock); - - if (avdtp_gen_bg_int) { - if (bt_service.bsmhcp_protocol->header.firmware_features & BSMHCP_FEATURE_AVDTP_TRANSFER_RING) { - uint32_t flags = 0; - - if (avdtp_hci && avdtp_hci->tsep_detect.tsep == BT_AVDTP_TSEP_SNK) - flags |= AVDTP_SNK_FLAG_TD_MASK; - if (avdtp_open) - flags |= AVDTP_OPEN_FLAG_TD_MASK; - scsc_bt_shm_h4_avdtp_detect_write(flags, cid_to_fw, hci_connection_handle); - } else { - /* Legacy communication between driver and FW. This was replaced by a transfer ring but - * the implementation is kept for backward compability - */ - u8 msg_counter = AVDTP_GET_MESSAGE_COUNT( - bt_service.bsmhcp_protocol->header.avdtp_detect_stream_id); - msg_counter++; - msg_counter &= 0x3; - - bt_service.bsmhcp_protocol->header.avdtp_detect_stream_id = cid_to_fw | - (hci_connection_handle << 16) | - (msg_counter << 28); - bt_service.bsmhcp_protocol->header.avdtp_detect_stream_id |= AVDTP_SIGNAL_FLAG_MASK; - if (is_sink) - bt_service.bsmhcp_protocol->header.avdtp_detect_stream_id |= AVDTP_SNK_FLAG_MASK; - SCSC_TAG_DEBUG( - BT_H4, - "Found AVDTP signal. msgid: 0x%02X, aclid: 0x%04X, cid: 0x%04X, streamid: 0x%08X\n", - msg_counter, - hci_connection_handle, - cid_to_fw, - bt_service.bsmhcp_protocol->header.avdtp_detect_stream_id); - mmiowb(); - scsc_service_mifintrbit_bit_set(bt_service.service, - bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, - SCSC_MIFINTR_TARGET_R4); - } - } -} - -/* Used to reset the different AVDTP detections */ -void scsc_avdtp_detect_reset(struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci, - bool reset_signal, - bool reset_signal_ongoing, - bool reset_stream, - bool reset_stream_ongoing, - bool reset_local_seids, - bool reset_remote_seids) -{ - if (reset_signal_ongoing) { - avdtp_hci->ongoing.outgoing_signal.state = BT_AVDTP_STATE_IDLE_SIGNALING; - avdtp_hci->ongoing.outgoing_signal.src_cid = 0; - avdtp_hci->ongoing.outgoing_signal.dst_cid = 0; - avdtp_hci->ongoing.incoming_signal.state = BT_AVDTP_STATE_IDLE_SIGNALING; - avdtp_hci->ongoing.incoming_signal.src_cid = 0; - avdtp_hci->ongoing.incoming_signal.dst_cid = 0; - } - if (reset_stream) { - avdtp_hci->stream.state = BT_AVDTP_STATE_IDLE_STREAMING; - avdtp_hci->stream.src_cid = 0; - avdtp_hci->stream.dst_cid = 0; - } - if (reset_stream_ongoing) { - avdtp_hci->ongoing.outgoing_stream.state = BT_AVDTP_STATE_IDLE_STREAMING; - avdtp_hci->ongoing.outgoing_stream.src_cid = 0; - avdtp_hci->ongoing.outgoing_stream.dst_cid = 0; - avdtp_hci->ongoing.incoming_stream.state = BT_AVDTP_STATE_IDLE_STREAMING; - avdtp_hci->ongoing.incoming_stream.src_cid = 0; - avdtp_hci->ongoing.incoming_stream.dst_cid = 0; - } - if (reset_local_seids) { - struct scsc_bt_avdtp_detect_snk_seid *seid = avdtp_hci->tsep_detect.local_snk_seids; - - while (seid) { - struct scsc_bt_avdtp_detect_snk_seid *next = seid->next; - - kfree(seid); - seid = next; - } - avdtp_hci->tsep_detect.local_snk_seids = NULL; - avdtp_hci->tsep_detect.local_snk_seid_candidate = 0; - } - if (reset_remote_seids) { - struct scsc_bt_avdtp_detect_snk_seid *seid = avdtp_hci->tsep_detect.remote_snk_seids; - - while (seid) { - struct scsc_bt_avdtp_detect_snk_seid *next = seid->next; - - kfree(seid); - seid = next; - } - avdtp_hci->tsep_detect.remote_snk_seids = NULL; - avdtp_hci->tsep_detect.remote_snk_seid_candidate = 0; - } - if (reset_local_seids && reset_remote_seids) - avdtp_hci->tsep_detect.tsep = BT_AVDTP_TSEP_SRC; - - if (reset_signal) { - struct scsc_bt_avdtp_detect_hci_connection *prev; - /* Unlock the mutex to keep the order of lock/unlock between the connection list - * and the individual elements - */ - spin_unlock(&avdtp_hci->lock); - spin_lock(&bt_service.avdtp_detect.lock); - /* The element could have been deleted at this point by another thread before the mutext - * on the list was taken. Therefore re-check. - */ - if (avdtp_hci) { - prev = bt_service.avdtp_detect.connections; - - if (prev && prev != avdtp_hci) { - /* The element was not the head of the list. Search for the previous element */ - while (prev) { - if (prev->next == avdtp_hci) { - /* Remove the element from the list */ - prev->next = avdtp_hci->next; - break; - } - prev = prev->next; - } - } else { - bt_service.avdtp_detect.connections = avdtp_hci->next; - } - /* Lock to make sure that no-one reads from it. Since it has been removed from the list - * unlocking it again will not make another thread read it since it cannot be found - */ - spin_lock(&avdtp_hci->lock); - spin_unlock(&bt_service.avdtp_detect.lock); - spin_unlock(&avdtp_hci->lock); - kfree(avdtp_hci); - avdtp_hci = NULL; - } else - spin_unlock(&bt_service.avdtp_detect.lock); - } -} - -/* Used to reset all current or ongoing detections for a given hci_connection_handle. This can e.g. - * used if the link is lost */ -bool scsc_avdtp_detect_reset_connection_handle(uint16_t hci_connection_handle) -{ - bool reset_anything = false; - struct scsc_bt_avdtp_detect_hci_connection *avdtp_hci = - scsc_avdtp_detect_find_or_create_hci_connection(hci_connection_handle, false); - - /* Check already established connections */ - if (avdtp_hci) { - scsc_avdtp_detect_reset(avdtp_hci, true, true, true, true, true, true); - /* No need to unlock the detection since it has been removed */ - reset_anything = true; - } - return reset_anything; -} - -void scsc_avdtp_detect_exit(void) -{ - struct scsc_bt_avdtp_detect_hci_connection *head; - - /* Lock the detection list and find the head */ - spin_lock(&bt_service.avdtp_detect.lock); - head = bt_service.avdtp_detect.connections; - - while (head) { - spin_lock(&head->lock); - /* Clear the remote and local seids lists on head */ - scsc_avdtp_detect_reset(head, false, false, false, false, true, true); - - /* Update the head to bypass the current element */ - bt_service.avdtp_detect.connections = head->next; - - spin_unlock(&bt_service.avdtp_detect.lock); - - /* Free the used memory */ - spin_unlock(&head->lock); - kfree(head); - head = NULL; - - /* Update the head variable */ - spin_lock(&bt_service.avdtp_detect.lock); - head = bt_service.avdtp_detect.connections; - } - - spin_unlock(&bt_service.avdtp_detect.lock); - - /* The avdtp_detect has now been restored and doesn't contain other information - * than its two locks - */ -} diff --git a/drivers/misc/samsung/scsc_bt/scsc_bluez.c b/drivers/misc/samsung/scsc_bt/scsc_bluez.c deleted file mode 100755 index 1c58f95c19f0..000000000000 --- a/drivers/misc/samsung/scsc_bt/scsc_bluez.c +++ /dev/null @@ -1,337 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - * BT BlueZ interface - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "../../../bluetooth/h4_recv.h" - -#include - -static struct hci_dev *hdev; -static struct device *dev_ref; -static const struct file_operations *bt_fs; -static struct workqueue_struct *wq; -static struct work_struct open_worker; -static struct work_struct close_worker; -static struct work_struct read_work; -static u8 receive_buffer[1024]; -static bool terminate_read; -static atomic_t *error_count_ref; -static wait_queue_head_t *read_wait_ref; -static struct file s_file; - -static struct platform_device *slsi_btz_pdev; -static struct rfkill *btz_rfkill; - -static const struct h4_recv_pkt scsc_recv_pkts[] = { - { H4_RECV_ACL, .recv = hci_recv_frame }, - { H4_RECV_EVENT, .recv = hci_recv_frame }, -}; - -static void slsi_bt_fs_read_func(struct work_struct *work) -{ - int ret; - struct sk_buff *skb = NULL; - - while ((ret = bt_fs->read(&s_file, receive_buffer, sizeof(receive_buffer), NULL)) >= 0) { - if (terminate_read) - break; - - if (ret > 0) { - skb = h4_recv_buf(hdev, skb, receive_buffer, - ret, scsc_recv_pkts, - ARRAY_SIZE(scsc_recv_pkts)); - - if (IS_ERR(skb)) { - SCSC_TAG_ERR(BT_COMMON, "corrupted event packet\n"); - hdev->stat.err_rx++; - break; - } - hdev->stat.byte_rx += ret; - } - } - - SCSC_TAG_INFO(BT_COMMON, "BT BlueZ: Exiting %s\n", __func__); -} - -static int slsi_bt_open(struct hci_dev *hdev) -{ - int err; - - SCSC_TAG_INFO(BT_COMMON, "enter\n"); - - err = bt_fs->open(NULL, NULL); - - if (0 == err) { - terminate_read = false; - if (wq == NULL) { - wq = create_singlethread_workqueue("slsi_bt_bluez_wq"); - INIT_WORK(&read_work, slsi_bt_fs_read_func); - } - queue_work(wq, &read_work); - } - - SCSC_TAG_INFO(BT_COMMON, "done\n"); - - return err; -} - -static int slsi_bt_close(struct hci_dev *hdev) -{ - int ret; - - SCSC_TAG_INFO(BT_COMMON, "terminating reader thread\n"); - - terminate_read = true; - - if (error_count_ref != NULL) - atomic_inc(error_count_ref); - - if (read_wait_ref != NULL) - wake_up(read_wait_ref); - - cancel_work_sync(&read_work); - - SCSC_TAG_INFO(BT_COMMON, "releasing service\n"); - - ret = bt_fs->release(NULL, NULL); - - if (wq != NULL) { - destroy_workqueue(wq); - wq = NULL; - } - - SCSC_TAG_INFO(BT_COMMON, "done\n"); - - return ret; -} - -static int slsi_bt_flush(struct hci_dev *hdev) -{ - return 0; -} - -static int slsi_bt_send_frame(struct hci_dev *hdev, struct sk_buff *skb) -{ - int ret; - - SCSC_TAG_DEBUG(BT_H4, "sending frame(data=%p, len=%u)\n", skb->data, skb->len); - - memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); - - ret = bt_fs->write(NULL, skb->data, skb->len, NULL); - if (ret >= 0) { - kfree_skb(skb); - - /* Update HCI stat counters */ - hdev->stat.byte_tx += skb->len; - - switch (hci_skb_pkt_type(skb)) { - case HCI_COMMAND_PKT: - hdev->stat.cmd_tx++; - break; - - case HCI_ACLDATA_PKT: - hdev->stat.acl_tx++; - break; - - case HCI_SCODATA_PKT: - hdev->stat.sco_tx++; - break; - } - } - - return ret; -} - -static void slsi_bt_open_worker(struct work_struct *work) -{ - int err; - - if (!hdev) { - hdev = hci_alloc_dev(); - if (!hdev) { - SCSC_TAG_ERR(BT_COMMON, "failed to allocate hci device\n"); - return; - } - - hdev->bus = HCI_VIRTUAL; - hdev->dev_type = HCI_BREDR; - - SET_HCIDEV_DEV(hdev, dev_ref); - - hdev->open = slsi_bt_open; - hdev->close = slsi_bt_close; - hdev->flush = slsi_bt_flush; - hdev->send = slsi_bt_send_frame; - - err = hci_register_dev(hdev); - if (err < 0) { - SCSC_TAG_ERR(BT_COMMON, "failed to register hci device (err: %d)\n", err); - hci_free_dev(hdev); - hdev = NULL; - } - } -} - -static void slsi_bt_close_worker(struct work_struct *work) -{ - if (hdev) { - hci_unregister_dev(hdev); - hci_free_dev(hdev); - hdev = NULL; - } -} - -void slsi_bt_notify_probe(struct device *dev, - const struct file_operations *fs, - atomic_t *error_count, - wait_queue_head_t *read_wait) -{ - bt_fs = fs; - error_count_ref = error_count; - read_wait_ref = read_wait; - dev_ref = dev; - - SCSC_TAG_INFO(BT_COMMON, "SLSI BT BlueZ probe\n"); -} - -void slsi_bt_notify_remove(void) -{ - error_count_ref = NULL; - read_wait_ref = NULL; - dev_ref = NULL; -} - -static int slsi_bt_power_control_set_param_cb(const char *buffer, - const struct kernel_param *kp) -{ - int ret; - u32 value; - - ret = kstrtou32(buffer, 0, &value); - if (!ret) { - if (value && dev_ref) { - INIT_WORK(&open_worker, slsi_bt_open_worker); - schedule_work(&open_worker); - } else if (0 == value) { - INIT_WORK(&close_worker, slsi_bt_close_worker); - schedule_work(&close_worker); - } - } - - return ret; -} - -static int slsi_bt_power_control_get_param_cb(char *buffer, - const struct kernel_param *kp) -{ - return sprintf(buffer, "%u\n", (hdev != NULL ? 1 : 0)); -} - -static struct kernel_param_ops slsi_bt_power_control_ops = { - .set = slsi_bt_power_control_set_param_cb, - .get = slsi_bt_power_control_get_param_cb, -}; - -module_param_cb(power_control, &slsi_bt_power_control_ops, NULL, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(power_control, - "Enables/disable BlueZ registration"); - -static int btz_rfkill_set(void *data, bool blocked) -{ - if (!blocked && dev_ref) { - INIT_WORK(&open_worker, slsi_bt_open_worker); - schedule_work(&open_worker); - } else if (blocked) { - INIT_WORK(&close_worker, slsi_bt_close_worker); - schedule_work(&close_worker); - } - - return 0; -} - -static const struct rfkill_ops btz_rfkill_ops = { - .set_block = btz_rfkill_set, -}; - -static int __init slsi_bluez_init(void) -{ - int ret; - - slsi_btz_pdev = platform_device_alloc("scsc-bluez", -1); - if (!slsi_btz_pdev) { - return -ENOMEM; - } - - ret = platform_device_add(slsi_btz_pdev); - if (ret) { - goto err_slsi_btz_pdev; - } - - btz_rfkill = rfkill_alloc("scsc-bluez-rfkill", &slsi_btz_pdev->dev, - RFKILL_TYPE_BLUETOOTH, &btz_rfkill_ops, NULL); - if (!btz_rfkill) { - goto err_btz_rfkill_alloc; - } - - rfkill_init_sw_state(btz_rfkill, 1); - - ret = rfkill_register(btz_rfkill); - if (ret) { - goto err_btz_rfkill_reg; - } - - return 0; - -err_btz_rfkill_reg: - rfkill_destroy(btz_rfkill); - -err_btz_rfkill_alloc: - platform_device_del(slsi_btz_pdev); - -err_slsi_btz_pdev: - platform_device_put(slsi_btz_pdev); - - return ret; -} - -static void __exit slsi_bluez_exit(void) -{ - platform_device_unregister(slsi_btz_pdev); - rfkill_unregister(btz_rfkill); - rfkill_destroy(btz_rfkill); -} - -module_init(slsi_bluez_init); -module_exit(slsi_bluez_exit); - -MODULE_DESCRIPTION("SCSC BT Bluez"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/misc/samsung/scsc_bt/scsc_bt_hci.h b/drivers/misc/samsung/scsc_bt/scsc_bt_hci.h deleted file mode 100755 index 02215bf0a277..000000000000 --- a/drivers/misc/samsung/scsc_bt/scsc_bt_hci.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** - * - * Internal BT driver HCI decoder - * - * Copyright (c) 2015 Samsung Electronics Co., Ltd - * - ****************************************************************************/ - -#ifndef __SCSC_BT_HCI_H -#define __SCSC_BT_HCI_H - -#define HCI_EVENT_HEADER_LENGTH (2) - -#define HCI_EV_INQUIRY_COMPLETE ((u8)0x01) -#define HCI_EV_INQUIRY_RESULT ((u8)0x02) -#define HCI_EV_CONN_COMPLETE ((u8)0x03) -#define HCI_EV_CONN_REQUEST ((u8)0x04) -#define HCI_EV_DISCONNECT_COMPLETE ((u8)0x05) -#define HCI_EV_AUTH_COMPLETE ((u8)0x06) -#define HCI_EV_REMOTE_NAME_REQ_COMPLETE ((u8)0x07) -#define HCI_EV_ENCRYPTION_CHANGE ((u8)0x08) -#define HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE ((u8)0x09) -#define HCI_EV_MASTER_LINK_KEY_COMPLETE ((u8)0x0A) -#define HCI_EV_READ_REM_SUPP_FEATURES_COMPLETE ((u8)0x0B) -#define HCI_EV_READ_REMOTE_VER_INFO_COMPLETE ((u8)0x0C) -#define HCI_EV_QOS_SETUP_COMPLETE ((u8)0x0D) -#define HCI_EV_COMMAND_COMPLETE ((u8)0x0E) -#define HCI_EV_COMMAND_STATUS ((u8)0x0F) -#define HCI_EV_HARDWARE_ERROR ((u8)0x10) -#define HCI_EV_FLUSH_OCCURRED ((u8)0x11) -#define HCI_EV_ROLE_CHANGE ((u8)0x12) -#define HCI_EV_NUMBER_COMPLETED_PKTS ((u8)0x13) -#define HCI_EV_MODE_CHANGE ((u8)0x14) -#define HCI_EV_RETURN_LINK_KEYS ((u8)0x15) -#define HCI_EV_PIN_CODE_REQ ((u8)0x16) -#define HCI_EV_LINK_KEY_REQ ((u8)0x17) -#define HCI_EV_LINK_KEY_NOTIFICATION ((u8)0x18) -#define HCI_EV_LOOPBACK_COMMAND ((u8)0x19) -#define HCI_EV_DATA_BUFFER_OVERFLOW ((u8)0x1A) -#define HCI_EV_MAX_SLOTS_CHANGE ((u8)0x1B) -#define HCI_EV_READ_CLOCK_OFFSET_COMPLETE ((u8)0x1C) -#define HCI_EV_CONN_PACKET_TYPE_CHANGED ((u8)0x1D) -#define HCI_EV_QOS_VIOLATION ((u8)0x1E) -#define HCI_EV_PAGE_SCAN_MODE_CHANGE ((u8)0x1F) -#define HCI_EV_PAGE_SCAN_REP_MODE_CHANGE ((u8)0x20) -/* 1.2 Events */ -#define HCI_EV_FLOW_SPEC_COMPLETE ((u8)0x21) -#define HCI_EV_INQUIRY_RESULT_WITH_RSSI ((u8)0x22) -#define HCI_EV_READ_REM_EXT_FEATURES_COMPLETE ((u8)0x23) -#define HCI_EV_FIXED_ADDRESS ((u8)0x24) -#define HCI_EV_ALIAS_ADDRESS ((u8)0x25) -#define HCI_EV_GENERATE_ALIAS_REQ ((u8)0x26) -#define HCI_EV_ACTIVE_ADDRESS ((u8)0x27) -#define HCI_EV_ALLOW_PRIVATE_PAIRING ((u8)0x28) -#define HCI_EV_ALIAS_ADDRESS_REQ ((u8)0x29) -#define HCI_EV_ALIAS_NOT_RECOGNISED ((u8)0x2A) -#define HCI_EV_FIXED_ADDRESS_ATTEMPT ((u8)0x2B) -#define HCI_EV_SYNC_CONN_COMPLETE ((u8)0x2C) -#define HCI_EV_SYNC_CONN_CHANGED ((u8)0x2D) - -/* 2.1 Events */ -#define HCI_EV_SNIFF_SUB_RATE ((u8)0x2E) -#define HCI_EV_EXTENDED_INQUIRY_RESULT ((u8)0x2F) -#define HCI_EV_ENCRYPTION_KEY_REFRESH_COMPLETE ((u8)0x30) -#define HCI_EV_IO_CAPABILITY_REQUEST ((u8)0x31) -#define HCI_EV_IO_CAPABILITY_RESPONSE ((u8)0x32) -#define HCI_EV_USER_CONFIRMATION_REQUEST ((u8)0x33) -#define HCI_EV_USER_PASSKEY_REQUEST ((u8)0x34) -#define HCI_EV_REMOTE_OOB_DATA_REQUEST ((u8)0x35) -#define HCI_EV_SIMPLE_PAIRING_COMPLETE ((u8)0x36) -#define HCI_EV_LST_CHANGE ((u8)0x38) -#define HCI_EV_ENHANCED_FLUSH_COMPLETE ((u8)0x39) -#define HCI_EV_USER_PASSKEY_NOTIFICATION ((u8)0x3B) -#define HCI_EV_KEYPRESS_NOTIFICATION ((u8)0x3C) -#define HCI_EV_REM_HOST_SUPPORTED_FEATURES ((u8)0x3D) -#define HCI_EV_ULP ((u8)0x3E) - -/* TCC + CSB Events */ -#define HCI_EV_TRIGGERED_CLOCK_CAPTURE ((u8)0x4E) -#define HCI_EV_SYNCHRONIZATION_TRAIN_COMPLETE ((u8)0x4F) -#define HCI_EV_SYNCHRONIZATION_TRAIN_RECEIVED ((u8)0x50) -#define HCI_EV_CSB_RECEIVE ((u8)0x51) -#define HCI_EV_CSB_TIMEOUT ((u8)0x52) -#define HCI_EV_TRUNCATED_PAGE_COMPLETE ((u8)0x53) -#define HCI_EV_SLAVE_PAGE_RESPONSE_TIMEOUT ((u8)0x54) -#define HCI_EV_CSB_CHANNEL_MAP_CHANGE ((u8)0x55) -#define HCI_EV_INQUIRY_RESPONSE_NOTIFICATION ((u8)0x56) - -/* 4.1 Events */ -#define HCI_EV_AUTHENTICATED_PAYLOAD_TIMEOUT_EXPIRED ((u8)0x57) - -/* ULP Sub-opcodes */ -#define HCI_EV_ULP_CONNECTION_COMPLETE ((u8)0x01) -#define HCI_EV_ULP_ADVERTISING_REPORT ((u8)0x02) -#define HCI_EV_ULP_CONNECTION_UPDATE_COMPLETE ((u8)0x03) -#define HCI_EV_ULP_READ_REMOTE_USED_FEATURES_COMPLETE ((u8)0x04) -#define HCI_EV_ULP_LONG_TERM_KEY_REQUEST ((u8)0x05) -#define HCI_EV_ULP_REMOTE_CONNECTION_PARAMETER_REQUEST ((u8)0x06) -#define HCI_EV_ULP_DATA_LENGTH_CHANGE ((u8)0x07) -#define HCI_EV_ULP_READ_LOCAL_P256_PUB_KEY_COMPLETE ((u8)0x08) -#define HCI_EV_ULP_GENERATE_DHKEY_COMPLETE ((u8)0x09) -#define HCI_EV_ULP_ENHANCED_CONNECTION_COMPLETE ((u8)0x0A) -#define HCI_EV_ULP_DIRECT_ADVERTISING_REPORT ((u8)0x0B) -#define HCI_EV_ULP_PHY_UPDATE_COMPLETE ((u8)0x0C) -/* The subevent code of ULP_USED_CHANNEL_SELECTION_EVENT shall be updated - when it is defined in the spec. - Assign it as 0x0D temporarily. */ -#define HCI_EV_ULP_USED_CHANNEL_SELECTION ((u8)0x0D) - -#define HCI_EV_DECODE(entry) case entry: ret = #entry; break - -#endif /* __SCSC_BT_HCI_H */ diff --git a/drivers/misc/samsung/scsc_bt/scsc_shm.c b/drivers/misc/samsung/scsc_bt/scsc_shm.c deleted file mode 100755 index e1786b37aaab..000000000000 --- a/drivers/misc/samsung/scsc_bt/scsc_shm.c +++ /dev/null @@ -1,1593 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2015 Samsung Electronics Co., Ltd - * - ****************************************************************************/ - -/* MX BT shared memory interface */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "scsc_bt_priv.h" -#include "scsc_shm.h" -#include "scsc_bt_hci.h" - -struct hci_credit_entry { - u16 hci_connection_handle; - u16 credits; -}; - -static u8 h4_write_buffer[BSMHCP_ACL_PACKET_SIZE + H4DMUX_HEADER_ACL]; -static u8 h4_acl_header[5]; -static u8 h4_hci_event_ncp_header[4 + BSMHCP_TRANSFER_RING_ACL_COUNT * sizeof(struct hci_credit_entry)]; -static u32 h4_hci_event_ncp_header_len = 8; -static struct hci_credit_entry *h4_hci_credit_entries = (struct hci_credit_entry *) &h4_hci_event_ncp_header[4]; -static u8 h4_hci_event_hardware_error[4] = { HCI_EVENT_PKT, HCI_EVENT_HARDWARE_ERROR_EVENT, 1, 0 }; -static u8 h4_iq_report_evt[HCI_IQ_REPORT_MAX_LEN]; -static u32 h4_iq_report_evt_len; - - -static void scsc_bt_shm_irq_handler(int irqbit, void *data) -{ - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(bt_service.service, irqbit); - - /* Ensure irq bit is cleared before reading the mailbox indexes */ - mb(); - - bt_service.interrupt_count++; - - /* Wake the reader operation */ - if (bt_service.bsmhcp_protocol->header.mailbox_hci_evt_write != - bt_service.bsmhcp_protocol->header.mailbox_hci_evt_read || - bt_service.bsmhcp_protocol->header.mailbox_acl_rx_write != - bt_service.bsmhcp_protocol->header.mailbox_acl_rx_read || - bt_service.bsmhcp_protocol->header.mailbox_acl_free_write != - bt_service.bsmhcp_protocol->header.mailbox_acl_free_read || - bt_service.bsmhcp_protocol->header.mailbox_iq_report_write != - bt_service.bsmhcp_protocol->header.mailbox_iq_report_read || - 0 != atomic_read(&bt_service.error_count) || - bt_service.bsmhcp_protocol->header.panic_deathbed_confession) { - bt_service.interrupt_read_count++; - - wake_lock_timeout(&bt_service.read_wake_lock, HZ); - wake_up(&bt_service.read_wait); - } - - if (bt_service.bsmhcp_protocol->header.mailbox_hci_cmd_write == - bt_service.bsmhcp_protocol->header.mailbox_hci_cmd_read && - bt_service.bsmhcp_protocol->header.mailbox_acl_tx_write == - bt_service.bsmhcp_protocol->header.mailbox_acl_tx_read) { - bt_service.interrupt_write_count++; - - if (wake_lock_active(&bt_service.write_wake_lock)) { - bt_service.write_wake_unlock_count++; - wake_unlock(&bt_service.write_wake_lock); - } - } -} - -/* Assign firmware/host interrupts */ -static void scsc_bt_shm_init_interrupt(void) -{ - /* To-host f/w IRQ allocations and ISR registrations */ - bt_service.bsmhcp_protocol->header.bg_to_ap_int_src = scsc_service_mifintrbit_register_tohost(bt_service.service, scsc_bt_shm_irq_handler, NULL); - bt_service.bsmhcp_protocol->header.fg_to_ap_int_src = scsc_service_mifintrbit_register_tohost(bt_service.service, scsc_bt_shm_irq_handler, NULL); - - /* From-host f/w IRQ allocations */ - bt_service.bsmhcp_protocol->header.ap_to_bg_int_src = scsc_service_mifintrbit_alloc_fromhost(bt_service.service, SCSC_MIFINTR_TARGET_R4); - bt_service.bsmhcp_protocol->header.ap_to_fg_int_src = scsc_service_mifintrbit_alloc_fromhost(bt_service.service, SCSC_MIFINTR_TARGET_R4); - bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src = scsc_service_mifintrbit_alloc_fromhost(bt_service.service, SCSC_MIFINTR_TARGET_M4); - - SCSC_TAG_DEBUG(BT_COMMON, "Registered to-host IRQ bits %d:%d:%d, from-host IRQ bits %d:%d\n", - bt_service.bsmhcp_protocol->header.bg_to_ap_int_src, - bt_service.bsmhcp_protocol->header.fg_to_ap_int_src, - bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src, - bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, - bt_service.bsmhcp_protocol->header.ap_to_fg_int_src); -} - -bool scsc_bt_shm_h4_avdtp_detect_write(uint32_t flags, - uint16_t l2cap_cid, - uint16_t hci_connection_handle) -{ - uint32_t tr_read; - uint32_t tr_write; - struct BSMHCP_TD_AVDTP *td; - - spin_lock(&bt_service.avdtp_detect.fw_write_lock); - - /* Store the read/write pointer on the stack since both are placed in unbuffered/uncached memory */ - tr_read = bt_service.bsmhcp_protocol->header.mailbox_avdtp_read; - tr_write = bt_service.bsmhcp_protocol->header.mailbox_avdtp_write; - - td = &bt_service.bsmhcp_protocol->avdtp_transfer_ring[tr_write]; - - SCSC_TAG_DEBUG(BT_H4, - "AVDTP_DETECT_PKT (flags: 0x%08X, cid: 0x%04X, handle: 0x%04X, read=%u, write=%u)\n", - flags, - l2cap_cid, - hci_connection_handle, - tr_read, - tr_write); - - /* Index out of bounds check */ - if (tr_read >= BSMHCP_TRANSFER_RING_AVDTP_SIZE || tr_write >= BSMHCP_TRANSFER_RING_AVDTP_SIZE) { - spin_unlock(&bt_service.avdtp_detect.fw_write_lock); - SCSC_TAG_ERR(BT_H4, - "AVDTP_DETECT_PKT - Index out of bounds (tr_read=%u, tr_write=%u)\n", - tr_read, - tr_write); - atomic_inc(&bt_service.error_count); - return false; - } - - /* Does the transfer ring have room for an entry */ - if (BSMHCP_HAS_ROOM(tr_write, tr_read, BSMHCP_TRANSFER_RING_AVDTP_SIZE)) { - /* Fill the transfer descriptor with the AVDTP data */ - td->flags = flags; - td->l2cap_cid = l2cap_cid; - td->hci_connection_handle = hci_connection_handle; - - /* Ensure the wake lock is acquired */ - if (!wake_lock_active(&bt_service.write_wake_lock)) { - bt_service.write_wake_lock_count++; - wake_lock(&bt_service.write_wake_lock); - } - - /* Increate the write pointer */ - BSMHCP_INCREASE_INDEX(tr_write, BSMHCP_TRANSFER_RING_AVDTP_SIZE); - bt_service.bsmhcp_protocol->header.mailbox_avdtp_write = tr_write; - - spin_unlock(&bt_service.avdtp_detect.fw_write_lock); - - /* Memory barrier to ensure out-of-order execution is completed */ - mmiowb(); - - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set( - bt_service.service, - bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, - SCSC_MIFINTR_TARGET_R4); - } else { - /* Transfer ring full */ - spin_unlock(&bt_service.avdtp_detect.fw_write_lock); - SCSC_TAG_ERR(BT_H4, - "AVDTP_DETECT_PKT - No more room for messages (tr_read=%u, tr_write=%u)\n", - tr_read, - tr_write); - scsc_service_force_panic(bt_service.service); - return false; - } - return true; -} - - -static ssize_t scsc_bt_shm_h4_hci_cmd_write(const unsigned char *data, size_t count) -{ - /* Store the read/write pointer on the stack since both are placed in unbuffered/uncached memory */ - uint32_t tr_read = bt_service.bsmhcp_protocol->header.mailbox_hci_cmd_read; - uint32_t tr_write = bt_service.bsmhcp_protocol->header.mailbox_hci_cmd_write; -#ifdef CONFIG_SCSC_PRINTK - uint16_t op_code = *(uint16_t *) data; -#endif - - /* Temp vars */ - struct BSMHCP_TD_CONTROL *td = &bt_service.bsmhcp_protocol->hci_cmd_transfer_ring[tr_write]; - - SCSC_TAG_DEBUG(BT_H4, "HCI_COMMAND_PKT (op_code=0x%04x, len=%zu, read=%u, write=%u)\n", op_code, count, tr_read, tr_write); - - /* Index out of bounds check */ - if (tr_read >= BSMHCP_TRANSFER_RING_CMD_SIZE || tr_write >= BSMHCP_TRANSFER_RING_CMD_SIZE) { - SCSC_TAG_ERR(BT_H4, "HCI_COMMAND_PKT - Index out of bounds (tr_read=%u, tr_write=%u)\n", tr_read, tr_write); - atomic_inc(&bt_service.error_count); - return -EIO; - } - - /* Does the transfer ring have room for an entry */ - if (BSMHCP_HAS_ROOM(tr_write, tr_read, BSMHCP_TRANSFER_RING_CMD_SIZE)) { - /* Fill the transfer descriptor with the HCI command data */ - memcpy(td->data, data, count); - td->length = (u16)count; - - /* Ensure the wake lock is acquired */ - if (!wake_lock_active(&bt_service.write_wake_lock)) { - bt_service.write_wake_lock_count++; - wake_lock(&bt_service.write_wake_lock); - } - - /* Increate the write pointer */ - BSMHCP_INCREASE_INDEX(tr_write, BSMHCP_TRANSFER_RING_CMD_SIZE); - bt_service.bsmhcp_protocol->header.mailbox_hci_cmd_write = tr_write; - - /* Memory barrier to ensure out-of-order execution is completed */ - mmiowb(); - - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, SCSC_MIFINTR_TARGET_R4); - } else - /* Transfer ring full. Only happens if the user attempt to send more HCI command packets than - * available credits */ - count = 0; - - return count; -} - -static ssize_t scsc_bt_shm_h4_acl_write(const unsigned char *data, size_t count) -{ - /* Store the read/write pointer on the stack since both are placed in unbuffered/uncached memory */ - uint32_t tr_read = bt_service.bsmhcp_protocol->header.mailbox_acl_tx_read; - uint32_t tr_write = bt_service.bsmhcp_protocol->header.mailbox_acl_tx_write; - - /* Temp vars */ - struct BSMHCP_TD_ACL_TX_DATA *td = &bt_service.bsmhcp_protocol->acl_tx_data_transfer_ring[tr_write]; - int acldata_buf_index = -1; - u16 l2cap_length; - u32 i; - size_t payload_len = count - ACLDATA_HEADER_SIZE; - - /* Index out of bounds check */ - if (tr_read >= BSMHCP_TRANSFER_RING_ACL_SIZE || tr_write >= BSMHCP_TRANSFER_RING_ACL_SIZE) { - SCSC_TAG_ERR(BT_H4, "ACL_DATA_PKT - Index out of bounds (tr_read=%u, tr_write=%u)\n", tr_read, tr_write); - atomic_inc(&bt_service.error_count); - return -EIO; - } - - /* Allocate a data slot */ - for (i = 0; i < BSMHCP_DATA_BUFFER_TX_ACL_SIZE; i++) { - /* Wrap the offset index around the buffer max */ - if (++bt_service.last_alloc == BSMHCP_DATA_BUFFER_TX_ACL_SIZE) - bt_service.last_alloc = 0; - /* Claim a free slot */ - if (bt_service.allocated[bt_service.last_alloc] == 0) { - bt_service.allocated[bt_service.last_alloc] = 1; - acldata_buf_index = bt_service.last_alloc; - bt_service.allocated_count++; - break; - } - } - - /* Is a buffer available to hold the data */ - if (acldata_buf_index < 0) { - SCSC_TAG_ERR(BT_H4, "ACL_DATA_PKT - No buffers available\n"); - atomic_inc(&bt_service.error_count); - return -EIO; - } - - /* Does the transfer ring have room for an entry */ - if (BSMHCP_HAS_ROOM(tr_write, tr_read, BSMHCP_TRANSFER_RING_ACL_SIZE)) { - /* Extract the ACL data header and L2CAP header and fill it into the transfer descriptor */ - td->buffer_index = (uint8_t)acldata_buf_index; - td->flags = HCI_ACL_DATA_FLAGS(data); - td->hci_connection_handle = HCI_ACL_DATA_CON_HDL(data); - td->length = (u16)payload_len; - - if ((td->flags & BSMHCP_ACL_BC_FLAG_BCAST_ACTIVE) || - (td->flags & BSMHCP_ACL_BC_FLAG_BCAST_ALL)) { - SCSC_TAG_DEBUG(BT_H4, - "Setting broadcast handle (hci_connection_handle=0x%03x)\n", - td->hci_connection_handle); - bt_service.connection_handle_list[td->hci_connection_handle].state = CONNECTION_ACTIVE; - } - - /* Is this a packet marked with the start flag */ - if ((td->flags & BSMHCP_ACL_PB_FLAG_MASK) == BSMHCP_ACL_PB_FLAG_START_NONFLUSH || - (td->flags & BSMHCP_ACL_PB_FLAG_MASK) == BSMHCP_ACL_PB_FLAG_START_FLUSH) { - - /* Extract the L2CAP payload length and connection identifier */ - td->l2cap_cid = HCI_L2CAP_CID(data); - - /* data+4 to skip the HCI header, to align offsets with the rx detection. The "true" argument is to tell - * the detection that this is TX */ - scsc_avdtp_detect_rxtx(td->hci_connection_handle, data+4, td->length, true); - - l2cap_length = HCI_L2CAP_LENGTH(data); - - SCSC_TAG_DEBUG(BT_TX, "ACL[START] (len=%u, buffer=%u, credits=%u, l2cap_cid=0x%04x, l2cap_length=%u)\n", - td->length, acldata_buf_index, - BSMHCP_DATA_BUFFER_TX_ACL_SIZE - (bt_service.allocated_count - bt_service.freed_count), - HCI_L2CAP_CID(data), l2cap_length); - - if (l2cap_length == payload_len - L2CAP_HEADER_SIZE) - /* Mark it with the END flag if packet length matches the L2CAP payload length */ - td->flags |= BSMHCP_ACL_L2CAP_FLAG_END; - else if (l2cap_length < payload_len - L2CAP_HEADER_SIZE) { - /* Mark it with the END flag if packet length is greater than the L2CAP payload length - and generate a warning notifying that this is incorrect according to the specification. - This is allowed to support the BITE tester. */ - SCSC_TAG_WARNING(BT_H4, "ACL_DATA_PKT - H4 ACL payload length > L2CAP Length (payload_len=%zu, l2cap_length=%u)\n", - payload_len - L2CAP_HEADER_SIZE, l2cap_length); - td->flags |= BSMHCP_ACL_L2CAP_FLAG_END; - } else if (l2cap_length > (payload_len - L2CAP_HEADER_SIZE)) { - /* This is only a fragment of the packet. Save the remaining number of octets required - * to complete the packet */ - bt_service.connection_handle_list[td->hci_connection_handle].length = (u16)(l2cap_length - payload_len + L2CAP_HEADER_SIZE); - bt_service.connection_handle_list[td->hci_connection_handle].l2cap_cid = HCI_L2CAP_CID(data); - } else { - /* The packet is larger than the L2CAP payload length - protocol error */ - SCSC_TAG_ERR(BT_H4, "ACL_DATA_PKT - L2CAP Length Error (l2cap_length=%u, payload_len=%zu)\n", - l2cap_length, payload_len - L2CAP_HEADER_SIZE); - atomic_inc(&bt_service.error_count); - return -EIO; - } - } else if ((td->flags & BSMHCP_ACL_PB_FLAG_MASK) == BSMHCP_ACL_PB_FLAG_CONT) { - /* Set the L2CAP connection identifer set by the start packet */ - td->l2cap_cid = bt_service.connection_handle_list[td->hci_connection_handle].l2cap_cid; - - SCSC_TAG_DEBUG(BT_TX, "ACL[CONT] (len=%u, buffer=%u, credits=%u, l2cap_cid=0x%04x, length=%u)\n", - td->length, acldata_buf_index, - BSMHCP_DATA_BUFFER_TX_ACL_SIZE - (bt_service.allocated_count - bt_service.freed_count), - bt_service.connection_handle_list[td->hci_connection_handle].l2cap_cid, - bt_service.connection_handle_list[td->hci_connection_handle].length); - - /* Does this packet complete the L2CAP frame */ - if (bt_service.connection_handle_list[td->hci_connection_handle].length == payload_len) { - /* The L2CAP frame is complete. mark it with the END flag */ - td->flags |= BSMHCP_ACL_L2CAP_FLAG_END; - - /* Set the remaining length to zero */ - bt_service.connection_handle_list[td->hci_connection_handle].length = 0; - } else if (bt_service.connection_handle_list[td->hci_connection_handle].length < payload_len) { - /* Mark it with the END flag if packet length is greater than the L2CAP missing payload length - and generate a warning notifying that this is incorrect according to the specification. - This is allowed to support the BITE tester. */ - SCSC_TAG_WARNING(BT_H4, "ACL_DATA_PKT - H4 ACL payload length > L2CAP Missing Length (payload_len=%zu, missing=%u)\n", - payload_len, bt_service.connection_handle_list[td->hci_connection_handle].length); - td->flags |= BSMHCP_ACL_L2CAP_FLAG_END; - /* Set the remaining length to zero */ - bt_service.connection_handle_list[td->hci_connection_handle].length = 0; - } else if (bt_service.connection_handle_list[td->hci_connection_handle].length > payload_len) - /* This is another fragment of the packet. Save the remaining number of octets required - * to complete the packet */ - bt_service.connection_handle_list[td->hci_connection_handle].length -= (u16)payload_len; - else if (bt_service.connection_handle_list[td->hci_connection_handle].length < payload_len) { - /* The packet is larger than the L2CAP payload length - protocol error */ - SCSC_TAG_ERR(BT_H4, "ACL_DATA_PKT - L2CAP Length Error (missing=%u, payload_len=%zu)\n", - bt_service.connection_handle_list[td->hci_connection_handle].length, payload_len); - atomic_inc(&bt_service.error_count); - return -EIO; - } - } else { - /* Reserved flags set - report it as an error */ - SCSC_TAG_ERR(BT_H4, "ACL_DATA_PKT - Flag set to reserved\n"); - atomic_inc(&bt_service.error_count); - return -EIO; - } - - SCSC_TAG_DEBUG(BT_H4, "ACL_DATA_PKT (len=%zu, read=%u, write=%u, slot=%u, flags=0x%04x, handle=0x%03x, l2cap_cid=0x%04x, missing=%u)\n", - payload_len, tr_read, tr_write, acldata_buf_index, td->flags >> 4, td->hci_connection_handle, td->l2cap_cid, - bt_service.connection_handle_list[td->hci_connection_handle].length); - - /* Ensure the wake lock is acquired */ - if (!wake_lock_active(&bt_service.write_wake_lock)) { - bt_service.write_wake_lock_count++; - wake_lock(&bt_service.write_wake_lock); - } - - /* Copy the ACL packet into the targer buffer */ - memcpy(&bt_service.bsmhcp_protocol->acl_tx_buffer[acldata_buf_index][0], &data[ACLDATA_HEADER_SIZE], payload_len); - /* Increate the write pointer */ - BSMHCP_INCREASE_INDEX(tr_write, BSMHCP_TRANSFER_RING_ACL_SIZE); - bt_service.bsmhcp_protocol->header.mailbox_acl_tx_write = tr_write; - - /* Memory barrier to ensure out-of-order execution is completed */ - mmiowb(); - - if (bt_service.bsmhcp_protocol->header.firmware_features & BSMHCP_FEATURE_M4_INTERRUPTS) - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set(bt_service.service, - bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src, SCSC_MIFINTR_TARGET_M4); - else - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set(bt_service.service, - bt_service.bsmhcp_protocol->header.ap_to_fg_int_src, SCSC_MIFINTR_TARGET_R4); - } else { - /* Transfer ring full. Only happens if the user attempt to send more ACL data packets than - * available credits */ - SCSC_TAG_ERR(BT_H4, "ACL_DATA_PKT - No room in transfer ring (tr_write=%u, tr_read=%u)\n", - tr_write, tr_read); - atomic_inc(&bt_service.error_count); - count = -EIO; - } - - return count; -} - -#ifdef CONFIG_SCSC_PRINTK -static const char *scsc_hci_evt_decode_event_code(u8 hci_event_code, u8 hci_ulp_sub_code) -{ - const char *ret = "NA"; - - switch (hci_event_code) { - HCI_EV_DECODE(HCI_EV_INQUIRY_COMPLETE); - HCI_EV_DECODE(HCI_EV_INQUIRY_RESULT); - HCI_EV_DECODE(HCI_EV_CONN_COMPLETE); - HCI_EV_DECODE(HCI_EV_CONN_REQUEST); - HCI_EV_DECODE(HCI_EV_DISCONNECT_COMPLETE); - HCI_EV_DECODE(HCI_EV_AUTH_COMPLETE); - HCI_EV_DECODE(HCI_EV_REMOTE_NAME_REQ_COMPLETE); - HCI_EV_DECODE(HCI_EV_ENCRYPTION_CHANGE); - HCI_EV_DECODE(HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE); - HCI_EV_DECODE(HCI_EV_MASTER_LINK_KEY_COMPLETE); - HCI_EV_DECODE(HCI_EV_READ_REM_SUPP_FEATURES_COMPLETE); - HCI_EV_DECODE(HCI_EV_READ_REMOTE_VER_INFO_COMPLETE); - HCI_EV_DECODE(HCI_EV_QOS_SETUP_COMPLETE); - HCI_EV_DECODE(HCI_EV_COMMAND_COMPLETE); - HCI_EV_DECODE(HCI_EV_COMMAND_STATUS); - HCI_EV_DECODE(HCI_EV_HARDWARE_ERROR); - HCI_EV_DECODE(HCI_EV_FLUSH_OCCURRED); - HCI_EV_DECODE(HCI_EV_ROLE_CHANGE); - HCI_EV_DECODE(HCI_EV_NUMBER_COMPLETED_PKTS); - HCI_EV_DECODE(HCI_EV_MODE_CHANGE); - HCI_EV_DECODE(HCI_EV_RETURN_LINK_KEYS); - HCI_EV_DECODE(HCI_EV_PIN_CODE_REQ); - HCI_EV_DECODE(HCI_EV_LINK_KEY_REQ); - HCI_EV_DECODE(HCI_EV_LINK_KEY_NOTIFICATION); - HCI_EV_DECODE(HCI_EV_LOOPBACK_COMMAND); - HCI_EV_DECODE(HCI_EV_DATA_BUFFER_OVERFLOW); - HCI_EV_DECODE(HCI_EV_MAX_SLOTS_CHANGE); - HCI_EV_DECODE(HCI_EV_READ_CLOCK_OFFSET_COMPLETE); - HCI_EV_DECODE(HCI_EV_CONN_PACKET_TYPE_CHANGED); - HCI_EV_DECODE(HCI_EV_QOS_VIOLATION); - HCI_EV_DECODE(HCI_EV_PAGE_SCAN_MODE_CHANGE); - HCI_EV_DECODE(HCI_EV_PAGE_SCAN_REP_MODE_CHANGE); - HCI_EV_DECODE(HCI_EV_FLOW_SPEC_COMPLETE); - HCI_EV_DECODE(HCI_EV_INQUIRY_RESULT_WITH_RSSI); - HCI_EV_DECODE(HCI_EV_READ_REM_EXT_FEATURES_COMPLETE); - HCI_EV_DECODE(HCI_EV_FIXED_ADDRESS); - HCI_EV_DECODE(HCI_EV_ALIAS_ADDRESS); - HCI_EV_DECODE(HCI_EV_GENERATE_ALIAS_REQ); - HCI_EV_DECODE(HCI_EV_ACTIVE_ADDRESS); - HCI_EV_DECODE(HCI_EV_ALLOW_PRIVATE_PAIRING); - HCI_EV_DECODE(HCI_EV_ALIAS_ADDRESS_REQ); - HCI_EV_DECODE(HCI_EV_ALIAS_NOT_RECOGNISED); - HCI_EV_DECODE(HCI_EV_FIXED_ADDRESS_ATTEMPT); - HCI_EV_DECODE(HCI_EV_SYNC_CONN_COMPLETE); - HCI_EV_DECODE(HCI_EV_SYNC_CONN_CHANGED); - HCI_EV_DECODE(HCI_EV_SNIFF_SUB_RATE); - HCI_EV_DECODE(HCI_EV_EXTENDED_INQUIRY_RESULT); - HCI_EV_DECODE(HCI_EV_ENCRYPTION_KEY_REFRESH_COMPLETE); - HCI_EV_DECODE(HCI_EV_IO_CAPABILITY_REQUEST); - HCI_EV_DECODE(HCI_EV_IO_CAPABILITY_RESPONSE); - HCI_EV_DECODE(HCI_EV_USER_CONFIRMATION_REQUEST); - HCI_EV_DECODE(HCI_EV_USER_PASSKEY_REQUEST); - HCI_EV_DECODE(HCI_EV_REMOTE_OOB_DATA_REQUEST); - HCI_EV_DECODE(HCI_EV_SIMPLE_PAIRING_COMPLETE); - HCI_EV_DECODE(HCI_EV_LST_CHANGE); - HCI_EV_DECODE(HCI_EV_ENHANCED_FLUSH_COMPLETE); - HCI_EV_DECODE(HCI_EV_USER_PASSKEY_NOTIFICATION); - HCI_EV_DECODE(HCI_EV_KEYPRESS_NOTIFICATION); - HCI_EV_DECODE(HCI_EV_REM_HOST_SUPPORTED_FEATURES); - HCI_EV_DECODE(HCI_EV_TRIGGERED_CLOCK_CAPTURE); - HCI_EV_DECODE(HCI_EV_SYNCHRONIZATION_TRAIN_COMPLETE); - HCI_EV_DECODE(HCI_EV_SYNCHRONIZATION_TRAIN_RECEIVED); - HCI_EV_DECODE(HCI_EV_CSB_RECEIVE); - HCI_EV_DECODE(HCI_EV_CSB_TIMEOUT); - HCI_EV_DECODE(HCI_EV_TRUNCATED_PAGE_COMPLETE); - HCI_EV_DECODE(HCI_EV_SLAVE_PAGE_RESPONSE_TIMEOUT); - HCI_EV_DECODE(HCI_EV_CSB_CHANNEL_MAP_CHANGE); - HCI_EV_DECODE(HCI_EV_INQUIRY_RESPONSE_NOTIFICATION); - HCI_EV_DECODE(HCI_EV_AUTHENTICATED_PAYLOAD_TIMEOUT_EXPIRED); - case HCI_EV_ULP: - { - switch (hci_ulp_sub_code) { - HCI_EV_DECODE(HCI_EV_ULP_CONNECTION_COMPLETE); - HCI_EV_DECODE(HCI_EV_ULP_ADVERTISING_REPORT); - HCI_EV_DECODE(HCI_EV_ULP_CONNECTION_UPDATE_COMPLETE); - HCI_EV_DECODE(HCI_EV_ULP_READ_REMOTE_USED_FEATURES_COMPLETE); - HCI_EV_DECODE(HCI_EV_ULP_LONG_TERM_KEY_REQUEST); - HCI_EV_DECODE(HCI_EV_ULP_REMOTE_CONNECTION_PARAMETER_REQUEST); - HCI_EV_DECODE(HCI_EV_ULP_DATA_LENGTH_CHANGE); - HCI_EV_DECODE(HCI_EV_ULP_READ_LOCAL_P256_PUB_KEY_COMPLETE); - HCI_EV_DECODE(HCI_EV_ULP_GENERATE_DHKEY_COMPLETE); - HCI_EV_DECODE(HCI_EV_ULP_ENHANCED_CONNECTION_COMPLETE); - HCI_EV_DECODE(HCI_EV_ULP_DIRECT_ADVERTISING_REPORT); - HCI_EV_DECODE(HCI_EV_ULP_PHY_UPDATE_COMPLETE); - HCI_EV_DECODE(HCI_EV_ULP_USED_CHANNEL_SELECTION); - } - break; - } - } - - return ret; -} -#endif - -static ssize_t scsc_iq_report_evt_read(char __user *buf, size_t len) -{ - ssize_t consumed = 0; - ssize_t ret = 0; - - /* Calculate the amount of data that can be transferred */ - len = min(h4_iq_report_evt_len - bt_service.read_offset, len); - - SCSC_TAG_DEBUG(BT_H4, "SCSC_IQ_REPORT_EVT_READ: td(h4_iq_len=%u offset=%u)\n", - h4_iq_report_evt_len, - bt_service.read_offset); - - /* Copy the data to the user buffer */ - ret = copy_to_user(buf, &h4_iq_report_evt[bt_service.read_offset], len); - if (ret == 0) { - /* All good - Update our consumed information */ - bt_service.read_offset += len; - consumed = len; - - SCSC_TAG_DEBUG(BT_H4, "SCSC_IQ_REPORT_EVT_READ: (offset=%u consumed: %u)\n", - bt_service.read_offset, - consumed); - - /* Have all data been copied to the userspace buffer */ - if (bt_service.read_offset == h4_iq_report_evt_len) { - /* All good - read operation is completed */ - bt_service.read_offset = 0; - bt_service.read_operation = BT_READ_OP_NONE; - } - } else { - SCSC_TAG_ERR(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - - return ret == 0 ? consumed : ret; -} - -static ssize_t scsc_hci_evt_read(char __user *buf, size_t len) -{ - struct BSMHCP_TD_HCI_EVT *td = &bt_service.bsmhcp_protocol->hci_evt_transfer_ring[bt_service.read_index]; - u8 h4_hci_event_header = HCI_EVENT_PKT; - ssize_t consumed = 0; - ssize_t ret = 0; - - SCSC_TAG_DEBUG(BT_H4, "td (length=%u, hci_connection_handle=0x%03x, event_type=%u), len=%zu, read_offset=%zu\n", - td->length, td->hci_connection_handle, td->event_type, len, bt_service.read_offset); - - /* Is this the start of the copy operation */ - if (0 == bt_service.read_offset) { - SCSC_TAG_DEBUG(BT_RX, "HCI Event [type=%s (0x%02x), length=%u]\n", - scsc_hci_evt_decode_event_code(td->data[0], td->data[2]), td->data[0], td->data[1]); - - if (td->data[1] + HCI_EVENT_HEADER_LENGTH != td->length) { - SCSC_TAG_ERR(BT_H4, "Firmware sent invalid HCI event\n"); - atomic_inc(&bt_service.error_count); - ret = -EFAULT; - } - - /* Store the H4 header in the user buffer */ - ret = copy_to_user(buf, &h4_hci_event_header, sizeof(h4_hci_event_header)); - if (0 == ret) { - /* All good - Update our consumed information */ - consumed = sizeof(h4_hci_event_header); - bt_service.read_offset = sizeof(h4_hci_event_header); - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - /* Can more data be put into the userspace buffer */ - if (0 == ret && (len - consumed)) { - /* Calculate the amount of data that can be transferred */ - len = min((td->length - (bt_service.read_offset - sizeof(h4_hci_event_header))), (len - consumed)); - - /* Copy the data to the user buffer */ - ret = copy_to_user(&buf[consumed], &td->data[bt_service.read_offset - sizeof(h4_hci_event_header)], len); - if (0 == ret) { - /* All good - Update our consumed information */ - bt_service.read_offset += len; - consumed += len; - - /* Have all data been copied to the userspace buffer */ - if (bt_service.read_offset == (sizeof(h4_hci_event_header) + td->length)) { - /* All good - read operation is completed */ - bt_service.read_offset = 0; - bt_service.read_operation = BT_READ_OP_NONE; - } - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - return 0 == ret ? consumed : ret; -} - -static ssize_t scsc_hci_evt_error_read(char __user *buf, size_t len) -{ - ssize_t ret; - ssize_t consumed = 0; - - /* Calculate the amount of data that can be transferred */ - len = min(sizeof(h4_hci_event_hardware_error) - bt_service.read_offset, len); - - /* Copy the data to the user buffer */ - ret = copy_to_user(buf, &h4_hci_event_hardware_error[bt_service.read_offset], len); - if (0 == ret) { - /* All good - Update our consumed information */ - bt_service.read_offset += len; - consumed = len; - - /* Have all data been copied to the userspace buffer */ - if (bt_service.read_offset == sizeof(h4_hci_event_hardware_error)) { - /* All good - read operation is completed */ - bt_service.read_offset = 0; - bt_service.read_operation = BT_READ_OP_NONE; - } - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - - return 0 == ret ? consumed : ret; -} - -static ssize_t scsc_acl_read(char __user *buf, size_t len) -{ - struct BSMHCP_TD_ACL_RX *td = &bt_service.bsmhcp_protocol->acl_rx_transfer_ring[bt_service.read_index]; - ssize_t consumed = 0; - size_t copy_len = 0; - ssize_t ret = 0; - - SCSC_TAG_DEBUG(BT_H4, "td (length=%u, hci_connection_handle=0x%03x, packet_boundary=%u, broadcast_flag=%u), len=%zu, read_offset=%zu\n", - td->length, td->hci_connection_handle, td->packet_boundary, td->broadcast_flag, len, bt_service.read_offset); - - /* Has the header been copied to userspace */ - if (bt_service.read_offset < sizeof(h4_acl_header)) { - /* Calculate the amount of data that can be transferred */ - copy_len = min(sizeof(h4_acl_header) - bt_service.read_offset, len); - - /* Fully generate the H4 header + ACL data header regardless of the available amount of user memory */ - h4_acl_header[0] = HCI_ACLDATA_PKT; - h4_acl_header[1] = td->hci_connection_handle & 0x00ff; - h4_acl_header[2] = ((td->hci_connection_handle & 0x0f00) >> 8) | ((td->packet_boundary & 0x03) << 4) | ((td->broadcast_flag & 0x03) << 6); - h4_acl_header[3] = td->length & 0x00ff; - h4_acl_header[4] = (td->length & 0xff00) >> 8; - - /* Copy the H4 header + ACL data header to the userspace buffer */ - ret = copy_to_user(buf, &h4_acl_header[bt_service.read_offset], copy_len); - if (0 == ret) { - /* All good - Update our consumed information */ - consumed = copy_len; - bt_service.read_offset += copy_len; - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - /* Can more data be put into the userspace buffer */ - if (0 == ret && bt_service.read_offset >= sizeof(h4_acl_header) && (len - consumed)) { - /* Calculate the amount of data that can be transferred */ - copy_len = min((td->length - (bt_service.read_offset - sizeof(h4_acl_header))), (len - consumed)); - - /* Copy the data to the user buffer */ - ret = copy_to_user(&buf[consumed], &td->data[bt_service.read_offset - sizeof(h4_acl_header)], copy_len); - if (0 == ret) { - /* All good - Update our consumed information */ - bt_service.read_offset += copy_len; - consumed += copy_len; - - /* Have all data been copied to the userspace buffer */ - if (bt_service.read_offset == (sizeof(h4_acl_header) + td->length)) { - /* All good - read operation is completed */ - bt_service.read_offset = 0; - bt_service.read_operation = BT_READ_OP_NONE; - - /* Only supported on start packet*/ - if (td->packet_boundary == HCI_ACL_PACKET_BOUNDARY_START_FLUSH) - /* The "false" argument is to tell the detection that this is RX */ - scsc_avdtp_detect_rxtx(td->hci_connection_handle, td->data, td->length, false); - } - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - SCSC_TAG_DEBUG(BT_H4, "read_offset=%zu, consumed=%zu, ret=%zd, len=%zu, copy_len=%zu\n", - bt_service.read_offset, consumed, ret, len, copy_len); - - return 0 == ret ? consumed : ret; -} - -static ssize_t scsc_acl_credit(char __user *buf, size_t len) -{ -#ifdef CONFIG_SCSC_PRINTK - struct BSMHCP_TD_ACL_TX_FREE *td = &bt_service.bsmhcp_protocol->acl_tx_free_transfer_ring[bt_service.read_index]; -#endif - ssize_t consumed = 0; - ssize_t ret = 0; - - SCSC_TAG_DEBUG(BT_H4, "td (hci_connection_handle=0x%03x, buffer_index=%u), len=%zu, read_offset=%zu\n", - td->hci_connection_handle & SCSC_BT_ACL_HANDLE_MASK, - td->buffer_index, len, bt_service.read_offset); - - /* Calculate the amount of data that can be transferred */ - len = min(h4_hci_event_ncp_header_len - bt_service.read_offset, len); - - /* Copy the data to the user buffer */ - ret = copy_to_user(buf, &h4_hci_event_ncp_header[bt_service.read_offset], len); - if (0 == ret) { - /* All good - Update our consumed information */ - bt_service.read_offset += len; - consumed = len; - - /* Have all data been copied to the userspace buffer */ - if (bt_service.read_offset == h4_hci_event_ncp_header_len) { - /* All good - read operation is completed */ - bt_service.read_offset = 0; - bt_service.read_operation = BT_READ_OP_NONE; - } - } else { - SCSC_TAG_WARNING(BT_H4, "copy_to_user returned: %zu\n", ret); - ret = -EACCES; - } - - return 0 == ret ? consumed : ret; -} - -static ssize_t scsc_bt_shm_h4_read_continue(char __user *buf, size_t len) -{ - ssize_t ret = 0; - - /* Is a HCI event read operation ongoing */ - if (BT_READ_OP_HCI_EVT == bt_service.read_operation) { - SCSC_TAG_DEBUG(BT_H4, "BT_READ_OP_HCI_EVT\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_hci_evt_read(buf, len); - if (BT_READ_OP_NONE == bt_service.read_operation) - /* All done - increase the read pointer and continue - * unless this was an out-of-order read for the queue - * sync helper */ - if (bt_service.read_index == bt_service.mailbox_hci_evt_read) - BSMHCP_INCREASE_INDEX(bt_service.mailbox_hci_evt_read, BSMHCP_TRANSFER_RING_EVT_SIZE); - /* Is a ACL data read operation ongoing */ - } else if (BT_READ_OP_ACL_DATA == bt_service.read_operation) { - SCSC_TAG_DEBUG(BT_H4, "BT_READ_OP_ACL_DATA\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_acl_read(buf, len); - if (BT_READ_OP_NONE == bt_service.read_operation) - /* All done - increase the read pointer and continue */ - BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_rx_read, BSMHCP_TRANSFER_RING_ACL_SIZE); - /* Is a ACL credit update operation ongoing */ - } else if (BT_READ_OP_ACL_CREDIT == bt_service.read_operation) { - SCSC_TAG_DEBUG(BT_H4, "BT_READ_OP_ACL_CREDIT\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_acl_credit(buf, len); - } else if (bt_service.read_operation == BT_READ_OP_IQ_REPORT) { - SCSC_TAG_DEBUG(BT_H4, "BT_READ_OP_IQ_REPORT\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_iq_report_evt_read(buf, len); - if (bt_service.read_operation == BT_READ_OP_NONE) - /* All done - increase the read pointer and continue */ - BSMHCP_INCREASE_INDEX(bt_service.mailbox_iq_report_read, BSMHCP_TRANSFER_RING_IQ_REPORT_SIZE); - } else if (BT_READ_OP_HCI_EVT_ERROR == bt_service.read_operation) { - SCSC_TAG_ERR(BT_H4, "BT_READ_OP_HCI_EVT_ERROR\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_hci_evt_error_read(buf, len); - if (BT_READ_OP_NONE == bt_service.read_operation) - /* All done - set the stop condition */ - bt_service.read_operation = BT_READ_OP_STOP; - } else if (BT_READ_OP_STOP == bt_service.read_operation) - ret = -EIO; - - return ret; -} - -static ssize_t scsc_bt_shm_h4_read_iq_report_evt(char __user *buf, size_t len) -{ - ssize_t ret = 0; - ssize_t consumed = 0; - - if (bt_service.read_operation == BT_READ_OP_NONE && - bt_service.mailbox_iq_report_read != bt_service.mailbox_iq_report_write) { - struct BSMHCP_TD_IQ_REPORTING_EVT *td = - &bt_service.bsmhcp_protocol->iq_reporting_transfer_ring[bt_service.mailbox_iq_report_read]; - u32 index = 0; - u32 j = 0; - u32 i; - - memset(h4_iq_report_evt, 0, sizeof(h4_iq_report_evt)); - h4_iq_report_evt_len = 0; - - h4_iq_report_evt[index++] = HCI_EVENT_PKT; - h4_iq_report_evt[index++] = 0x3E; - index++; /* Leaving room for total length of params */ - h4_iq_report_evt[index++] = td->subevent_code; - - if (td->subevent_code == HCI_LE_CONNECTIONLESS_IQ_REPORT_EVENT_SUB_CODE) { - /* LE Connectionless IQ Report Event*/ - h4_iq_report_evt[index++] = td->sync_handle & 0xFF; - h4_iq_report_evt[index++] = (td->sync_handle >> 8) & 0xFF; - } else if (td->subevent_code == HCI_LE_CONNECTION_IQ_REPORT_EVENT_SUB_CODE) { - /* LE connection IQ Report Event */ - h4_iq_report_evt[index++] = td->connection_handle & 0xFF; - h4_iq_report_evt[index++] = (td->connection_handle >> 8) & 0xFF; - h4_iq_report_evt[index++] = td->rx_phy; - - } - h4_iq_report_evt[index++] = td->channel_index; - h4_iq_report_evt[index++] = td->rssi & 0xFF; - h4_iq_report_evt[index++] = (td->rssi >> 8) & 0xFF; - h4_iq_report_evt[index++] = td->rssi_antenna_id; - h4_iq_report_evt[index++] = td->cte_type; - h4_iq_report_evt[index++] = td->slot_durations; - h4_iq_report_evt[index++] = td->packet_status; - h4_iq_report_evt[index++] = td->event_count & 0xFF; - h4_iq_report_evt[index++] = (td->event_count >> 8) & 0xFF; - h4_iq_report_evt[index++] = td->sample_count; - - /* Total length of hci event */ - h4_iq_report_evt_len = index + (2 * td->sample_count); - - /* Total length of hci event parameters */ - h4_iq_report_evt[2] = h4_iq_report_evt_len - 3; - - for (i = 0; i < td->sample_count; i++) { - h4_iq_report_evt[index + i] = td->data[j++]; - h4_iq_report_evt[(index + td->sample_count) + i] = td->data[j++]; - } - - bt_service.read_operation = BT_READ_OP_IQ_REPORT; - bt_service.read_index = bt_service.mailbox_iq_report_read; - - ret = scsc_iq_report_evt_read(&buf[consumed], len - consumed); - if (ret > 0) { - /* All good - Update our consumed information */ - consumed += ret; - ret = 0; - - /** - * Update the index if all the data could be copied to the userspace - * buffer otherwise stop processing the HCI events - */ - if (bt_service.read_operation == BT_READ_OP_NONE) - BSMHCP_INCREASE_INDEX(bt_service.mailbox_iq_report_read, - BSMHCP_TRANSFER_RING_IQ_REPORT_SIZE); - } - } - - return ret == 0 ? consumed : ret; -} - -static ssize_t scsc_bt_shm_h4_read_hci_evt(char __user *buf, size_t len) -{ - ssize_t ret = 0; - ssize_t consumed = 0; - - while (BT_READ_OP_NONE == bt_service.read_operation && 0 == ret && !bt_service.hci_event_paused && bt_service.mailbox_hci_evt_read != bt_service.mailbox_hci_evt_write) { - struct BSMHCP_TD_HCI_EVT *td = &bt_service.bsmhcp_protocol->hci_evt_transfer_ring[bt_service.mailbox_hci_evt_read]; - - /* This event has already been processed - skip it */ - if (bt_service.processed[bt_service.mailbox_hci_evt_read]) { - bt_service.processed[bt_service.mailbox_hci_evt_read] = false; - BSMHCP_INCREASE_INDEX(bt_service.mailbox_hci_evt_read, BSMHCP_TRANSFER_RING_EVT_SIZE); - continue; - } - - /* A connection event has been detected by the firmware */ - if (td->event_type & BSMHCP_EVENT_TYPE_CONNECTED) { - /* Sanity check of the HCI connection handle */ - if (td->hci_connection_handle >= SCSC_BT_CONNECTION_INFO_MAX) { - SCSC_TAG_ERR(BT_H4, "connection handle is beyond max (hci_connection_handle=0x%03x)\n", - td->hci_connection_handle); - atomic_inc(&bt_service.error_count); - break; - } - - SCSC_TAG_DEBUG(BT_H4, "connected (hci_connection_handle=0x%03x, state=%u)\n", - td->hci_connection_handle, bt_service.connection_handle_list[td->hci_connection_handle].state); - - /* Update the connection table to mark it as active */ - bt_service.connection_handle_list[td->hci_connection_handle].state = CONNECTION_ACTIVE; - bt_service.connection_handle_list[td->hci_connection_handle].length = 0; - - /* ACL data processing can now continue */ - bt_service.acldata_paused = false; - - /* A disconnection event has been detected by the firmware */ - } else if (td->event_type & BSMHCP_EVENT_TYPE_DISCONNECTED) { - SCSC_TAG_DEBUG(BT_H4, "disconnected (hci_connection_handle=0x%03x, state=%u)\n", - td->hci_connection_handle, bt_service.connection_handle_list[td->hci_connection_handle].state); - - /* If this ACL connection had an avdtp stream, mark it gone and interrupt the bg */ - if (scsc_avdtp_detect_reset_connection_handle(td->hci_connection_handle)) - mmiowb(); - - /* If the connection is marked as active the ACL disconnect packet hasn't yet arrived */ - if (CONNECTION_ACTIVE == bt_service.connection_handle_list[td->hci_connection_handle].state) { - /* Pause the HCI event procssing until the ACL disconnect packet arrives */ - bt_service.hci_event_paused = true; - break; - } - - /* Firmware does not have more ACL data - Mark the connection as inactive */ - bt_service.connection_handle_list[td->hci_connection_handle].state = CONNECTION_NONE; - } - - /* Start a HCI event copy to userspace */ - bt_service.read_operation = BT_READ_OP_HCI_EVT; - bt_service.read_index = bt_service.mailbox_hci_evt_read; - ret = scsc_hci_evt_read(&buf[consumed], len - consumed); - if (ret > 0) { - /* All good - Update our consumed information */ - consumed += ret; - ret = 0; - - /* Update the index if all the data could be copied to the userspace buffer otherwise stop processing the HCI events */ - if (BT_READ_OP_NONE == bt_service.read_operation) - BSMHCP_INCREASE_INDEX(bt_service.mailbox_hci_evt_read, BSMHCP_TRANSFER_RING_EVT_SIZE); - else - break; - } - } - - return 0 == ret ? consumed : ret; -} - -/** - * Start the acl data to userspace copy - * - * Acl processing should be stopped if either unable to read a complete packet - * or a complete packet is read and BlueZ is enabled - * - * @param[out] ret result of read operations written to here - * @param[in,out] consumed read bytes added to this - * - * @return true if ACL data processing should stop - */ -static bool scsc_bt_shm_h4_acl_start_copy(char __user *buf, - size_t len, - ssize_t *ret, - ssize_t *consumed) -{ - bt_service.read_operation = BT_READ_OP_ACL_DATA; - bt_service.read_index = bt_service.mailbox_acl_rx_read; - *ret = scsc_acl_read(&buf[*consumed], len - *consumed); - if (*ret <= 0) - return *ret < 0; /* Break the loop for errors */ - - /* Update our consumed information */ - *consumed += *ret; - *ret = 0; - - /* Stop processing if all the data could not be copied to userspace */ - if (bt_service.read_operation != BT_READ_OP_NONE) - return true; - - BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_rx_read, BSMHCP_TRANSFER_RING_ACL_SIZE); - - return false; -} - -static ssize_t scsc_bt_shm_h4_read_acl_data(char __user *buf, size_t len) -{ - ssize_t ret = 0; - ssize_t consumed = 0; - - while (bt_service.read_operation == BT_READ_OP_NONE && - !bt_service.acldata_paused && - bt_service.mailbox_acl_rx_read != bt_service.mailbox_acl_rx_write) { - struct BSMHCP_TD_ACL_RX *td = &bt_service.bsmhcp_protocol->acl_rx_transfer_ring[bt_service.mailbox_acl_rx_read]; - - /* Bypass packet inspection and connection handling for data dump */ - if (SCSC_BT_ACL_RAW == (td->hci_connection_handle & SCSC_BT_ACL_RAW_MASK)) { - if (scsc_bt_shm_h4_acl_start_copy(buf, len, &ret, &consumed)) - break; - } - - /* Sanity check of the HCI connection handle */ - if (td->hci_connection_handle >= SCSC_BT_CONNECTION_INFO_MAX) { - SCSC_TAG_ERR(BT_H4, "connection handle is beyond max (hci_connection_handle=0x%03x)\n", - td->hci_connection_handle); - atomic_inc(&bt_service.error_count); - break; - } - - /* Only process ACL data if the connection is marked active aka a HCI connection complete event has arrived */ - if (CONNECTION_ACTIVE == bt_service.connection_handle_list[td->hci_connection_handle].state) { - /* Is this the final packet for the indicated ACL connection */ - if (td->disconnected) { - SCSC_TAG_DEBUG(BT_H4, "ACL disconnected (hci_connection_handle=0x%03x, state=%u)\n", - td->hci_connection_handle, bt_service.connection_handle_list[td->hci_connection_handle].state); - - /* Update the connection table to mark it as disconnected */ - bt_service.connection_handle_list[td->hci_connection_handle].state = CONNECTION_DISCONNECTED; - - /* Clear the HCI event processing to allow for the HCI disconnect event to be transferred to userspace */ - bt_service.hci_event_paused = false; - - /* Update the read pointer */ - BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_rx_read, BSMHCP_TRANSFER_RING_ACL_SIZE); - } else { - if (scsc_bt_shm_h4_acl_start_copy(buf, len, &ret, &consumed)) - break; - } - /* If the connection state is inactive the HCI connection complete information hasn't yet arrived. Stop processing ACL data */ - } else if (CONNECTION_NONE == bt_service.connection_handle_list[td->hci_connection_handle].state) { - SCSC_TAG_DEBUG(BT_H4, "ACL empty (hci_connection_handle=0x%03x, state=%u)\n", - td->hci_connection_handle, bt_service.connection_handle_list[td->hci_connection_handle].state); - bt_service.acldata_paused = true; - /* If the connection state is disconnection the firmware sent ACL after the ACL disconnect packet which is an FW error */ - } else { - SCSC_TAG_ERR(BT_H4, "ACL data received after disconnected indication\n"); - atomic_inc(&bt_service.error_count); - break; - } - } - - return 0 == ret ? consumed : ret; -} - -static ssize_t scsc_bt_shm_h4_read_acl_credit(char __user *buf, size_t len) -{ - ssize_t ret = 0; - ssize_t consumed = 0; - - if (BT_READ_OP_NONE == bt_service.read_operation && 0 == ret && - bt_service.mailbox_acl_free_read != bt_service.mailbox_acl_free_write) { - u32 entries = 0; - u32 index; - - memset(h4_hci_event_ncp_header, 0, sizeof(h4_hci_event_ncp_header)); - - while (bt_service.mailbox_acl_free_read != bt_service.mailbox_acl_free_write) { - struct BSMHCP_TD_ACL_TX_FREE *td = - &bt_service.bsmhcp_protocol->acl_tx_free_transfer_ring[bt_service.mailbox_acl_free_read]; - uint16_t sanitized_conn_handle = td->hci_connection_handle & SCSC_BT_ACL_HANDLE_MASK; - - if (bt_service.connection_handle_list[sanitized_conn_handle].state == CONNECTION_ACTIVE) { - for (index = 0; index < BSMHCP_TRANSFER_RING_ACL_COUNT; index++) { - if (0 == h4_hci_credit_entries[index].hci_connection_handle) { - h4_hci_credit_entries[index].hci_connection_handle = - td->hci_connection_handle; - h4_hci_credit_entries[index].credits = 1; - entries++; - break; - } else if ((h4_hci_credit_entries[index].hci_connection_handle & - SCSC_BT_ACL_HANDLE_MASK) == sanitized_conn_handle) { - h4_hci_credit_entries[index].hci_connection_handle = - td->hci_connection_handle; - h4_hci_credit_entries[index].credits++; - break; - } - } - } else - SCSC_TAG_WARNING(BT_H4, - "No active connection ((hci_connection_handle=0x%03x)\n", - sanitized_conn_handle); - - BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_free_read, BSMHCP_TRANSFER_RING_ACL_SIZE); - } - - if (entries) { - /* Fill the number of completed packets data into the temp buffer */ - h4_hci_event_ncp_header[0] = HCI_EVENT_PKT; - h4_hci_event_ncp_header[1] = HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS_EVENT; - h4_hci_event_ncp_header[2] = 1 + (4 * entries); /* Parameter length */ - h4_hci_event_ncp_header[3] = entries; /* Number_of_Handles */ - h4_hci_event_ncp_header_len = 4 + (4 * entries); - - /* Start a ACL credit copy to userspace */ - bt_service.read_operation = BT_READ_OP_ACL_CREDIT; - bt_service.read_index = bt_service.mailbox_acl_free_read; - ret = scsc_acl_credit(&buf[consumed], len - consumed); - if (ret > 0) { - /* Update our consumed information */ - consumed += ret; - ret = 0; - } - } - } - - return 0 == ret ? consumed : ret; -} - -ssize_t scsc_bt_shm_h4_queue_sync_helper(char __user *buf, size_t len) -{ - ssize_t ret = 0; - bool found = false; - u32 mailbox_hci_evt_read = bt_service.mailbox_hci_evt_read; - - /* If both the HCI event transfer ring and ACL data transfer ring has been - * paused the entire HCI event transfer ring is scanned for the presence - * of the connected indication. Once present this is transferred to the host - * stack and marked as processed. This will unlock the hci event processing */ - while (bt_service.hci_event_paused && bt_service.acldata_paused) { - struct BSMHCP_TD_ACL_RX *acl_td = &bt_service.bsmhcp_protocol->acl_rx_transfer_ring[bt_service.mailbox_acl_rx_read]; - - while (mailbox_hci_evt_read != bt_service.mailbox_hci_evt_write) { - struct BSMHCP_TD_HCI_EVT *td = &bt_service.bsmhcp_protocol->hci_evt_transfer_ring[mailbox_hci_evt_read]; - - if (td->event_type & BSMHCP_EVENT_TYPE_CONNECTED && acl_td->hci_connection_handle == td->hci_connection_handle) { - /* Update the connection table to mark it as active */ - bt_service.connection_handle_list[td->hci_connection_handle].state = CONNECTION_ACTIVE; - bt_service.connection_handle_list[td->hci_connection_handle].length = 0; - - /* ACL data processing can now continue */ - bt_service.acldata_paused = false; - - /* Mark the event as processed */ - bt_service.processed[mailbox_hci_evt_read] = true; - - /* Indicate the event have been found */ - found = true; - - /* Start a HCI event copy to userspace */ - bt_service.read_operation = BT_READ_OP_HCI_EVT; - bt_service.read_index = mailbox_hci_evt_read; - ret = scsc_hci_evt_read(buf, len); - break; - } - - BSMHCP_INCREASE_INDEX(mailbox_hci_evt_read, BSMHCP_TRANSFER_RING_EVT_SIZE); - } - - if (!found) { - ret = wait_event_interruptible_timeout(bt_service.read_wait, - ((mailbox_hci_evt_read != bt_service.bsmhcp_protocol->header.mailbox_hci_evt_write || - 0 != atomic_read(&bt_service.error_count) || - bt_service.bsmhcp_protocol->header.panic_deathbed_confession)), HZ); - if (0 == ret) { - SCSC_TAG_ERR(BT_H4, "firmware didn't send the connected event within the given timeframe\n"); - atomic_inc(&bt_service.error_count); - break; - } else if (1 != ret) { - SCSC_TAG_INFO(BT_H4, "user interrupt\n"); - break; - } - } - } - - return ret; -} - -ssize_t scsc_bt_shm_h4_read(struct file *file, char __user *buf, size_t len, loff_t *offset) -{ - ssize_t consumed = 0; - ssize_t ret = 0; - ssize_t res; - bool gen_bg_int = false; - bool gen_fg_int = false; - - if (len == 0) - return 0; - - /* Only 1 reader is allowed */ - if (1 != atomic_inc_return(&bt_service.h4_readers)) { - atomic_dec(&bt_service.h4_readers); - return -EIO; - } - - /* Update the cached variables with the non-cached variables */ - bt_service.mailbox_hci_evt_write = bt_service.bsmhcp_protocol->header.mailbox_hci_evt_write; - bt_service.mailbox_acl_rx_write = bt_service.bsmhcp_protocol->header.mailbox_acl_rx_write; - bt_service.mailbox_acl_free_write = bt_service.bsmhcp_protocol->header.mailbox_acl_free_write; - bt_service.mailbox_iq_report_write = bt_service.bsmhcp_protocol->header.mailbox_iq_report_write; - - /* Only generate the HCI hardware error event if any pending operation has been completed - * and the event hasn't already neen sent. This check assume the main while loop will exit - * on a completed operation in the next section */ - if (0 != atomic_read(&bt_service.error_count) && BT_READ_OP_NONE == bt_service.read_operation) - bt_service.read_operation = BT_READ_OP_HCI_EVT_ERROR; - - /* put the remaining data from the transfer ring into the available userspace buffer */ - if (BT_READ_OP_NONE != bt_service.read_operation) { - ret = scsc_bt_shm_h4_read_continue(buf, len); - /* Update the consumed variable in case a operation was ongoing */ - if (0 < ret) { - consumed = ret; - ret = 0; - } - } - - /* Main loop - Can only be entered when no operation is present on entering this function - * or no hardware error has been detected. It loops until data has been placed in the - * userspace buffer or an error has been detected */ - while (0 == atomic_read(&bt_service.error_count) && 0 == consumed) { - /* If both the HCI event processing and ACL data processing has been disabled this function - * helps exit this condition by scanning the HCI event queue for the connection established - * event and return it to userspace */ - ret = scsc_bt_shm_h4_queue_sync_helper(buf, len); - if (ret > 0) { - consumed = ret; - break; - } - - /* Does any of the read/write pairs differs */ - if ((bt_service.mailbox_hci_evt_read == bt_service.mailbox_hci_evt_write || bt_service.hci_event_paused) && - (bt_service.mailbox_acl_rx_read == bt_service.mailbox_acl_rx_write || bt_service.acldata_paused) && - bt_service.mailbox_acl_free_read == bt_service.mailbox_acl_free_write && - bt_service.mailbox_iq_report_read == bt_service.mailbox_iq_report_write && - 0 == atomic_read(&bt_service.error_count) && - 0 == bt_service.bsmhcp_protocol->header.panic_deathbed_confession) { - /* Don't wait if in NONBLOCK mode */ - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - /* All read/write pairs are identical - wait for the firmware. The conditional - * check is used to verify that a read/write pair has actually changed */ - ret = wait_event_interruptible( - bt_service.read_wait, - ((bt_service.mailbox_hci_evt_read != - bt_service.bsmhcp_protocol->header.mailbox_hci_evt_write && - !bt_service.hci_event_paused) || - (bt_service.mailbox_acl_rx_read != - bt_service.bsmhcp_protocol->header.mailbox_acl_rx_write && - !bt_service.acldata_paused) || - (bt_service.mailbox_acl_free_read != - bt_service.bsmhcp_protocol->header.mailbox_acl_free_write) || - (bt_service.mailbox_iq_report_read != - bt_service.bsmhcp_protocol->header.mailbox_iq_report_write) || - atomic_read(&bt_service.error_count) != 0 || - bt_service.bsmhcp_protocol->header.panic_deathbed_confession)); - - /* Has an error been detected elsewhere in the driver then just return from this function */ - if (0 != atomic_read(&bt_service.error_count)) - break; - - /* Any failures is handled by the userspace application */ - if (ret) - break; - - /* Refresh our write indexes before starting to process the protocol */ - bt_service.mailbox_hci_evt_write = bt_service.bsmhcp_protocol->header.mailbox_hci_evt_write; - bt_service.mailbox_acl_rx_write = bt_service.bsmhcp_protocol->header.mailbox_acl_rx_write; - bt_service.mailbox_acl_free_write = bt_service.bsmhcp_protocol->header.mailbox_acl_free_write; - bt_service.mailbox_iq_report_write = bt_service.bsmhcp_protocol->header.mailbox_iq_report_write; - } - - SCSC_TAG_DEBUG(BT_H4, "hci_evt_read=%u, hci_evt_write=%u, acl_rx_read=%u,acl_rx_write=%u\n", - bt_service.mailbox_hci_evt_read, - bt_service.mailbox_hci_evt_write, - bt_service.mailbox_acl_rx_read, - bt_service.mailbox_acl_rx_write); - - SCSC_TAG_DEBUG(BT_H4, "acl_free_read=%u, acl_free_write=%u, iq_report_read=%u iq_report_write=%u\n", - bt_service.mailbox_acl_free_read, - bt_service.mailbox_acl_free_write, - bt_service.mailbox_iq_report_read, - bt_service.mailbox_iq_report_write); - - SCSC_TAG_DEBUG(BT_H4, "read_operation=%u, hci_event_paused=%u, acldata_paused=%u\n", - bt_service.read_operation, bt_service.hci_event_paused, - bt_service.acldata_paused); - - while (bt_service.mailbox_acl_free_read_scan != bt_service.mailbox_acl_free_write) { - struct BSMHCP_TD_ACL_TX_FREE *td = &bt_service.bsmhcp_protocol->acl_tx_free_transfer_ring[bt_service.mailbox_acl_free_read_scan]; - - /* Free the buffer in the allocation table */ - if (td->buffer_index < BSMHCP_DATA_BUFFER_TX_ACL_SIZE) { - bt_service.allocated[td->buffer_index] = 0; - bt_service.freed_count++; - - SCSC_TAG_DEBUG(BT_TX, "ACL[CREDIT] (index=%u, buffer=%u, credits=%u)\n", - bt_service.mailbox_acl_free_read_scan, - td->buffer_index, - BSMHCP_DATA_BUFFER_TX_ACL_SIZE - (bt_service.allocated_count - bt_service.freed_count)); - } - - BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_free_read_scan, BSMHCP_TRANSFER_RING_ACL_SIZE); - } - - /* First: process any pending HCI event that needs to be sent to userspace */ - res = scsc_bt_shm_h4_read_hci_evt(&buf[consumed], len - consumed); - if (res < 0) { - ret = res; - break; - } - consumed += res; - - /* Second: process any pending ACL data that needs to be sent to userspace */ - res = scsc_bt_shm_h4_read_acl_data(&buf[consumed], len - consumed); - if (res < 0) { - ret = res; - break; - } - consumed += res; - - /* Third: process any pending ACL data that needs to be sent to userspace */ - res = scsc_bt_shm_h4_read_acl_credit(&buf[consumed], len - consumed); - if (res < 0) { - ret = res; - break; - } - consumed += res; - - res = scsc_bt_shm_h4_read_iq_report_evt(&buf[consumed], len - consumed); - if (res < 0) { - ret = res; - break; - } - consumed += res; - } - - if (0 == ret && 0 == consumed) { - if (0 != atomic_read(&bt_service.error_count) && BT_READ_OP_NONE == bt_service.read_operation) - bt_service.read_operation = BT_READ_OP_HCI_EVT_ERROR; - - if (BT_READ_OP_HCI_EVT_ERROR == bt_service.read_operation) { - SCSC_TAG_DEBUG(BT_H4, "BT_READ_OP_HCI_EVT_ERROR\n"); - - /* Copy data into the userspace buffer */ - ret = scsc_hci_evt_error_read(buf, len); - if (ret > 0) { - consumed += ret; - ret = 0; - } - - if (BT_READ_OP_NONE == bt_service.read_operation) - /* All done - set the stop condition */ - bt_service.read_operation = BT_READ_OP_STOP; - } - } - - /* If anything was read, generate the appropriate interrupt(s) */ - if (bt_service.bsmhcp_protocol->header.mailbox_hci_evt_read != - bt_service.mailbox_hci_evt_read) - gen_bg_int = true; - - if (bt_service.bsmhcp_protocol->header.mailbox_acl_rx_read != - bt_service.mailbox_acl_rx_read || - bt_service.bsmhcp_protocol->header.mailbox_acl_free_read != - bt_service.mailbox_acl_free_read) - gen_fg_int = true; - - if (bt_service.bsmhcp_protocol->header.mailbox_iq_report_read != - bt_service.mailbox_iq_report_read) - gen_fg_int = true; - - - /* Update the read index for all transfer rings */ - bt_service.bsmhcp_protocol->header.mailbox_hci_evt_read = bt_service.mailbox_hci_evt_read; - bt_service.bsmhcp_protocol->header.mailbox_acl_rx_read = bt_service.mailbox_acl_rx_read; - bt_service.bsmhcp_protocol->header.mailbox_acl_free_read = bt_service.mailbox_acl_free_read; - bt_service.bsmhcp_protocol->header.mailbox_iq_report_read = bt_service.mailbox_iq_report_read; - - /* Ensure the data is updating correctly in memory */ - mmiowb(); - - if (gen_bg_int) - scsc_service_mifintrbit_bit_set(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, SCSC_MIFINTR_TARGET_R4); - - if (gen_fg_int) { - if (bt_service.bsmhcp_protocol->header.firmware_features & BSMHCP_FEATURE_M4_INTERRUPTS) - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set(bt_service.service, - bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src, SCSC_MIFINTR_TARGET_M4); - else - /* Trigger the interrupt in the mailbox */ - scsc_service_mifintrbit_bit_set(bt_service.service, - bt_service.bsmhcp_protocol->header.ap_to_fg_int_src, SCSC_MIFINTR_TARGET_R4); - } - - if (BT_READ_OP_STOP != bt_service.read_operation) - SCSC_TAG_DEBUG(BT_H4, "hci_evt_read=%u, acl_rx_read=%u, acl_free_read=%u, read_operation=%u, consumed=%zd, ret=%zd\n", - bt_service.mailbox_hci_evt_read, bt_service.mailbox_acl_rx_read, bt_service.mailbox_acl_free_read, bt_service.read_operation, consumed, ret); - - /* Decrease the H4 readers counter */ - atomic_dec(&bt_service.h4_readers); - - return 0 == ret ? consumed : ret; -} - -ssize_t scsc_bt_shm_h4_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) -{ - size_t length; - size_t hci_pkt_len; - ssize_t written = 0; - ssize_t ret = 0; - - SCSC_TAG_DEBUG(BT_H4, "enter\n"); - - UNUSED(file); - UNUSED(offset); - - /* Only 1 writer is allowed */ - if (1 != atomic_inc_return(&bt_service.h4_writers)) { - atomic_dec(&bt_service.h4_writers); - return -EIO; - } - - /* Has en error been detect then just return with an error */ - if (0 != atomic_read(&bt_service.error_count)) { - /* SCSC_TAG_WARNING(BT_H4, "firmware panicked or protocol error (error_count=%u)\n", atomic_read(&bt_service.error_count));*/ - atomic_dec(&bt_service.h4_writers); - return -EIO; - } - - while (written != count && 0 == ret) { - length = min(count - written, sizeof(h4_write_buffer) - bt_service.h4_write_offset); - SCSC_TAG_DEBUG(BT_H4, "count: %zu, length: %zu, h4_write_offset: %zu, written:%zu, size:%zu\n", - count, length, bt_service.h4_write_offset, written, sizeof(h4_write_buffer)); - - /* Is there room in the temp buffer */ - if (0 == length) { - SCSC_TAG_ERR(BT_H4, "no room in the buffer\n"); - atomic_inc(&bt_service.error_count); - ret = -EIO; - break; - } - - /* Copy the userspace data to the target buffer */ - ret = copy_from_user(&h4_write_buffer[bt_service.h4_write_offset], &buf[written], length); - if (0 == ret) { - /* Is there enough data to include a HCI command header and is the type a HCI_COMMAND_PKT */ - if ((length + bt_service.h4_write_offset) >= H4DMUX_HEADER_HCI && HCI_COMMAND_PKT == h4_write_buffer[0]) { - /* Extract the HCI command packet length */ - hci_pkt_len = h4_write_buffer[3] + 3; - - /* Is it a complete packet available */ - if ((hci_pkt_len + 1) <= (length + bt_service.h4_write_offset)) { - /* Transfer the packet to the HCI command transfer ring */ - ret = scsc_bt_shm_h4_hci_cmd_write(&h4_write_buffer[1], hci_pkt_len); - if (ret >= 0) { - written += ((hci_pkt_len + 1) - bt_service.h4_write_offset); - bt_service.h4_write_offset = 0; - ret = 0; - } - } else { - /* Still needing data to have the complete packet */ - SCSC_TAG_WARNING(BT_H4, "missing data (need=%zu, got=%zu)\n", (hci_pkt_len + 1), (length + bt_service.h4_write_offset)); - written += length; - bt_service.h4_write_offset += (u32) length; - } - /* Is there enough data to include a ACL data header and is the type a HCI_ACLDATA_PKT */ - } else if ((length + bt_service.h4_write_offset) >= H4DMUX_HEADER_ACL && HCI_ACLDATA_PKT == h4_write_buffer[0]) { - /* Extract the ACL data packet length */ - hci_pkt_len = (h4_write_buffer[3] | (h4_write_buffer[4] << 8)); - - /* Sanity check on the packet length */ - if (hci_pkt_len > BSMHCP_ACL_PACKET_SIZE) { - SCSC_TAG_ERR(BT_H4, "ACL packet length is larger than read buffer size specifies (%zu > %u)\n", hci_pkt_len, BSMHCP_ACL_PACKET_SIZE); - atomic_inc(&bt_service.error_count); - ret = -EIO; - break; - } - - /* Is it a complete packet available */ - if ((hci_pkt_len + 5) <= (length + bt_service.h4_write_offset)) { - /* Transfer the packet to the ACL data transfer ring */ - ret = scsc_bt_shm_h4_acl_write(&h4_write_buffer[1], hci_pkt_len + 4); - if (ret >= 0) { - written += ((hci_pkt_len + 5) - bt_service.h4_write_offset); - bt_service.h4_write_offset = 0; - ret = 0; - } - } else { - /* Still needing data to have the complete packet */ - SCSC_TAG_WARNING(BT_H4, "missing data (need=%zu, got=%zu)\n", (hci_pkt_len + 5), (length - bt_service.h4_write_offset)); - written += length; - bt_service.h4_write_offset += (u32) length; - } - /* Is there less data than a header then just wait for more */ - } else if (length <= 5) { - bt_service.h4_write_offset += length; - written += length; - /* Header is unknown - unable to proceed */ - } else { - atomic_inc(&bt_service.error_count); - ret = -EIO; - } - } else { - SCSC_TAG_WARNING(BT_H4, "copy_from_user returned: %zu\n", ret); - ret = -EACCES; - } - } - - SCSC_TAG_DEBUG(BT_H4, "h4_write_offset=%zu, ret=%zu, written=%zu\n", - bt_service.h4_write_offset, ret, written); - - /* Decrease the H4 readers counter */ - atomic_dec(&bt_service.h4_writers); - - return 0 == ret ? written : ret; -} - -unsigned scsc_bt_shm_h4_poll(struct file *file, poll_table *wait) -{ - /* Add the wait queue to the polling queue */ - poll_wait(file, &bt_service.read_wait, wait); - - /* Has en error been detect then just return with an error */ - if (bt_service.bsmhcp_protocol->header.mailbox_hci_evt_write != - bt_service.bsmhcp_protocol->header.mailbox_hci_evt_read || - bt_service.bsmhcp_protocol->header.mailbox_acl_rx_write != - bt_service.bsmhcp_protocol->header.mailbox_acl_rx_read || - bt_service.bsmhcp_protocol->header.mailbox_acl_free_write != - bt_service.bsmhcp_protocol->header.mailbox_acl_free_read || - bt_service.bsmhcp_protocol->header.mailbox_iq_report_write != - bt_service.bsmhcp_protocol->header.mailbox_iq_report_read || - (bt_service.read_operation != BT_READ_OP_NONE && - bt_service.read_operation != BT_READ_OP_STOP) || - ((BT_READ_OP_STOP != bt_service.read_operation) && - (0 != atomic_read(&bt_service.error_count) || - bt_service.bsmhcp_protocol->header.panic_deathbed_confession))) { - SCSC_TAG_DEBUG(BT_H4, "queue(s) changed\n"); - return POLLIN | POLLRDNORM; /* readeable */ - } - - SCSC_TAG_DEBUG(BT_H4, "no change\n"); - - return POLLOUT; /* writeable */ -} - -/* Initialise the shared memory interface */ -int scsc_bt_shm_init(void) -{ - /* Get kmem pointer to the shared memory ref */ - bt_service.bsmhcp_protocol = scsc_mx_service_mif_addr_to_ptr(bt_service.service, bt_service.bsmhcp_ref); - if (bt_service.bsmhcp_protocol == NULL) { - SCSC_TAG_ERR(BT_COMMON, "couldn't map kmem to shm_ref 0x%08x\n", (u32)bt_service.bsmhcp_ref); - return -ENOMEM; - } - - /* Clear the protocol shared memory area */ - memset(bt_service.bsmhcp_protocol, 0, sizeof(*bt_service.bsmhcp_protocol)); - bt_service.bsmhcp_protocol->header.magic_value = BSMHCP_PROTOCOL_MAGICVALUE; - bt_service.mailbox_hci_evt_read = 0; - bt_service.mailbox_acl_rx_read = 0; - bt_service.mailbox_acl_free_read = 0; - bt_service.mailbox_acl_free_read_scan = 0; - bt_service.mailbox_iq_report_read = 0; - bt_service.read_index = 0; - bt_service.allocated_count = 0; - - /* Initialise the interrupt handlers */ - scsc_bt_shm_init_interrupt(); - - return 0; -} - -/* Terminate the shared memory interface, stopping its thread. - * - * Note: The service must be stopped prior to calling this function. - * The shared memory can only be released after calling this function. - */ -void scsc_bt_shm_exit(void) -{ - /* Release IRQs */ - if (bt_service.bsmhcp_protocol != NULL) { - scsc_service_mifintrbit_unregister_tohost(bt_service.service, bt_service.bsmhcp_protocol->header.bg_to_ap_int_src); - scsc_service_mifintrbit_unregister_tohost(bt_service.service, bt_service.bsmhcp_protocol->header.fg_to_ap_int_src); - - scsc_service_mifintrbit_free_fromhost(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, SCSC_MIFINTR_TARGET_R4); - scsc_service_mifintrbit_free_fromhost(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_fg_int_src, SCSC_MIFINTR_TARGET_R4); - scsc_service_mifintrbit_free_fromhost(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src, SCSC_MIFINTR_TARGET_M4); - } - - /* Clear all control structures */ - bt_service.last_alloc = 0; - bt_service.hci_event_paused = false; - bt_service.acldata_paused = false; - bt_service.bsmhcp_protocol = NULL; - - memset(bt_service.allocated, 0, sizeof(bt_service.allocated)); - memset(bt_service.connection_handle_list, 0, sizeof(bt_service.connection_handle_list)); -} - diff --git a/drivers/misc/samsung/scsc_bt/scsc_shm.h b/drivers/misc/samsung/scsc_bt/scsc_shm.h deleted file mode 100644 index 6b98e7d8fdb8..000000000000 --- a/drivers/misc/samsung/scsc_bt/scsc_shm.h +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2015 Samsung Electronics Co., Ltd - * - ****************************************************************************/ - -/* Shared memory interface API */ - -#ifndef __SCSC_SHM_H__ -#define __SCSC_SHM_H__ -#include -#include - -/* Bluetooth specific functions */ -int scsc_bt_shm_init(void); -void scsc_bt_shm_exit(void); -ssize_t scsc_bt_shm_h4_read(struct file *file, - char __user *buf, - size_t len, - loff_t *offset); -ssize_t scsc_bt_shm_h4_write(struct file *file, - const char __user *buf, - size_t len, loff_t *offset); -unsigned scsc_bt_shm_h4_poll(struct file *file, poll_table *wait); - -/* ANT specific functions */ -int scsc_ant_shm_init(void); -void scsc_ant_shm_exit(void); -ssize_t scsc_shm_ant_read(struct file *file, - char __user *buf, - size_t len, - loff_t *offset); -ssize_t scsc_shm_ant_write(struct file *file, - const char __user *buf, - size_t len, loff_t *offset); -unsigned int scsc_shm_ant_poll(struct file *file, poll_table *wait); -#endif diff --git a/drivers/net/wireless/scsc/Kconfig b/drivers/net/wireless/scsc/Kconfig deleted file mode 100755 index bccc2711fbef..000000000000 --- a/drivers/net/wireless/scsc/Kconfig +++ /dev/null @@ -1,270 +0,0 @@ -config SCSC_WLAN - tristate "Driver for Samsung SCSC Maxwell Wifi" - depends on SCSC_CORE - depends on CFG80211 - -if SCSC_WLAN != n -config SCSC_WLAN_KEY_MGMT_OFFLOAD - bool "Enable roam offload for SCSC WLAN" - default y - ---help--- - This option enables roam offload for SCSC WLAN. - -config SCSC_WLAN_HIP4_PROFILING - bool "Enable HIP4 profiling" - default y - depends on SCSC_WLAN - ---help--- - This option enables HIP4 profiling - -config SCSC_WLAN_DEBUG - bool "Enable debug output from the SCSC Wifi driver" - depends on SCSC_WLAN - select SCSC_WLAN_HIP4_PROFILING - ---help--- - This option enables debug support for the SCSC wifi chipset. - -config SCSC_WLAN_SG - bool "Enable SCSC WLAN Scatter-gather and GSO support" - depends on SCSC_WLAN - default y - ---help--- - This option enables scatter-gather and GSO feature - -config SCSC_WLAN_SKB_TRACKING - bool "Enable debug memory tracking of skb data in the driver" - ---help--- - This option enables tracking of all skb data in the driver.. - This will affect the performance! - -config SCSC_WLAN_RX_NAPI - bool "Enable use of net device napi rx polling api" - default y - ---help--- - This option enables the drivers use of the napi api - -config SCSC_WLAN_RX_NAPI_GRO - bool "Enable use of net device napi rx GRO" - depends on SCSC_WLAN_RX_NAPI - default y - ---help--- - This option enables the drivers use of the napi Generic Receive Offload - -config SCSC_WLAN_ANDROID - bool "Android specific support" - default y - ---help--- - Enable support for Android specific aspects of the driver. - -config SCSC_WLAN_STA_ONLY - bool "Support WLAN STA only (no P2P/AP/IBSS)" - default n - ---help--- - Enable only basic STA mode for debugging purposes - -config SCSC_WLAN_KIC_OPS - bool "Wi-Fi service driver provides OPS for KIC to use for various tasks" - depends on SAMSUNG_KIC - default y - ---help--- - Provide Wi-Fi service driver OPS, which KIC can use for triggering Wi-Fi related events. - -config SCSC_WLAN_GSCAN_ENABLE - bool "Enable GSCAN in SCSC wlan driver" - default y - ---help--- - This option enables GSCAN in SCSC wlan driver. - -config SCSC_WLAN_WES_NCHO - bool "Enable NCHO/WES feature" - default y - ---help--- - This option enables the NCHO/WES feature - -config SCSC_WLAN_MUTEX_DEBUG - bool "Enable Mutex debugging mechanism in slsi wlan driver" - default y - ---help--- - This option enables the Mutex debug reports in slsi wlan driver. - -config CONFIG_SCSC_WLAN_BLOCK_IPV6 - bool "Block IPv6" - default n - ---help--- - This option blocks IPv6 packets. - -config CONFIG_SCSC_WLAN_DISABLE_NAT_KA - bool "Disable NAT" - default n - ---help--- - This option disables NAT. - -config SCSC_WLAN_HANG_TEST - bool "Test HANG Event" - default y - ---help--- - This option facilitates triggering of HANG Event - to reset WLAN. - -config SCSC_WLAN_NAT_KEEPALIVE_DISABLE - bool "Disable NAT KeepAlive" - default n - ---help--- - This option disables the NAT KeepAlive - Offload Feature. - -config SCSC_WLAN_ENHANCED_LOGGING - bool "Enable Enhanced Logging" - depends on SCSC_WIFILOGGER - default y - ---help--- - This option enables the Enhanced Logging - Feature. - -config SCSC_WLAN_ACM_API - bool "Provide TSF read API" - default n - ---help--- - This option provides API to read TSF. - -endif - -config SCSC_WLAN_MAC_ADDRESS_FILENAME - string "MAC address filename" - default "/efs/wifi/.mac.info" - ---help--- - Select the programmed MAC address file. - -config SCSC_WLAN_MAX_INTERFACES - int "Max number of virtual interfaces supported" - range 1 3 - default 3 - ---help--- - The driver structures are sized to support this - number of interfaces. - -config SCSC_WLAN_AP_INFO_FILE - bool "Create .softap.info file" - default n - ---help--- - The option enables the driver to create .softap.info - file in user space and fill information in it. - -config SCSC_WLAN_WIFI_SHARING - bool "Wifi Sharing Support" - default n - ---help--- - This option tells if wifi sharing is supported or not. - -config SCSC_WLAN_SAE_CONFIG - bool "Wpa3 Support" - default n - ---help--- - This option tells if wpa3 is supported or not. - -config SCSC_WLAN_ENABLE_MAC_RANDOMISATION - bool "Wifi Mac Randomization Support" - default n - ---help--- - This option tells if mac randomization is supported or not. - -config SCSC_WLAN_SINGLE_ANTENNA - depends on SCSC_WLAN_WIFI_SHARING - bool "Single Antenna Supported" - default y - ---help--- - This option tells if there is support for single - antenna or dual antenna. - -config SCSC_AP_INTERFACE_NAME - string "AP net device interface name" - default "wlan1" - ---help--- - AP net device interface name. - -config SCSC_WLAN_ACS_ENABLE - bool "ACS Support" - default y - ---help--- - This option tells if automatic channel selection is - supported or not. - -config SCSC_AP_INTERFACE_NAME - string "AP net device interface name" - default "wlan1" - ---help--- - AP net device interface name. - -config SCSC_WLAN_MHS_STATIC_INTERFACE - bool "Static AP Interface Support" - default n - ---help--- - This option tells if AP interface has been created - statically or dynamically. - is enabled or not. - -config SCSC_WLAN_PRIORITISE_IMP_FRAMES - bool "Change priority of important frames such as DNS, MDNS, TCP SYN" - default y - ---help--- - The option enables the driver to prioritise important frames - (such as DNS, MDNS, TCP SYN) so that they are sent ahead of others. - -config SCSC_WIFI_NAN_ENABLE - bool "Enable WiFi NAN" - default n - ---help--- - This option tells whether WiFi NAN is enabled or not. - -config SCSC_WLAN_ENHANCED_PKT_FILTER - bool "Enable enhanced packet filtering in suspend" - default n - ---help--- - This option tells if UDP packet filtering in suspend is - supported or not. - -config SCSC_WLAN_SET_NUM_ANTENNAS - bool "Enable configuring of number of antennas" - default n - ---help--- - This option tells whether configuring of number of antennas is enabled or not. - -config SCSC_ENHANCED_PACKET_STATS - bool "Enable enhanced packet stats" - default n - ---help--- - This option tells whether enhanced packet stats collection - is enabled or not. - -config SCSC_WLAN_LOW_LATENCY_MODE - bool "Support enabling/disabling roaming as per latency mode" - default n - ---help--- - This option tells whether support is provided for enabling - or disabling roaming as per the latency mode. - -config SCSC_WLAN_SET_PREFERRED_ANTENNA - bool "Enable the driver to set preferred antenna" - default y - ---help--- - This option enables the driver to set the preferred antenna. - -config SLSI_WLAN_STA_FWD_BEACON - bool "Forwarding beacon support" - default n - ---help--- - This option tells if beacon forwarding in STA mode is enabled or not. - When it is enabled, Driver deliver beacon info of connected AP to Supplicant. - -config SCSC_WLAN_STA_ENHANCED_ARP_DETECT - bool "Enable enhanced arp detection" - default n - ---help--- - This option tells whether enhanced arp detection - is enabled or not. - -config SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER - bool "Enable abnormal multicast packet filtering in suspend" - default n - ---help--- - This option tells if abnormal multicast packet filtering in suspend is supported or not. diff --git a/drivers/net/wireless/scsc/Makefile b/drivers/net/wireless/scsc/Makefile deleted file mode 100755 index 8abcb20895ae..000000000000 --- a/drivers/net/wireless/scsc/Makefile +++ /dev/null @@ -1,127 +0,0 @@ -# ---------------------------------------------------------------------------- -# FILE: Makefile -# -# PURPOSE: -# Build instructions for SCSC Wlan driver. -# -# Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved -# ---------------------------------------------------------------------------- - -# Needed since this subdir is symlinked in the main Kernel tree -# without this our samsung subdir is NOT cleaned. -clean-files := *.o *.ko - -obj-$(CONFIG_SCSC_WLAN) += scsc_wlan.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += hip4.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += mbulk.o - -# ---------------------------------------------------------------------------- -# HIP4 sampler -# ---------------------------------------------------------------------------- -ifeq ($(CONFIG_SCSC_WLAN_HIP4_PROFILING),y) -scsc_wlan-$(CONFIG_SCSC_WLAN) += hip4_sampler.o -endif - -scsc_wlan-$(CONFIG_SCSC_SMAPPER) += hip4_smapper.o - -# Upper driver -scsc_wlan-$(CONFIG_SCSC_WLAN) += dev.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += cfg80211_ops.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += netif.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += rx.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += tx.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += ba.o - -# SAPs -scsc_wlan-$(CONFIG_SCSC_WLAN) += sap_mlme.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += sap_ma.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += sap_dbg.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += sap_test.o - -# ---------------------------------------------------------------------------- -# Common Driver Files -# ---------------------------------------------------------------------------- -scsc_wlan-$(CONFIG_SCSC_WLAN) += mib.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += mib_text_convert.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += debug.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += debug_frame.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += procfs.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += mgt.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += mlme.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += udi.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += log_clients.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += src_sink.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += fw_test.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += cac.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += scsc_wifi_fcq.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += ioctl.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += wakelock.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += traffic_monitor.o - -# ---------------------------------------------------------------------------- -# ACM -# ---------------------------------------------------------------------------- -ifeq ($(CONFIG_SCSC_WLAN_ACM_API),y) -scsc_wlan-$(CONFIG_SCSC_WLAN) += acm_api.o -endif - -# ---------------------------------------------------------------------------- -# Building for Hardware -# ---------------------------------------------------------------------------- -scsc_wlan-$(CONFIG_SCSC_WLAN) += hip.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += cm_if.o - -ifeq ($(CONFIG_SCSC_WLAN_KIC_OPS),y) -scsc_wlan-$(CONFIG_SCSC_WLAN) += kic.o -endif -ccflags-$(CONFIG_SCSC_WLAN_KIC_OPS) += -DCONFIG_SCSC_WLAN_KIC_OPS - -ifeq ($(CONFIG_SCSC_WLAN_GSCAN_ENABLE),y) -scsc_wlan-$(CONFIG_SCSC_WLAN) += nl80211_vendor.o -ccflags-y += -DCONFIG_SCSC_WLAN_GSCAN_ENABLE -endif -ifeq ($(CONFIG_SCSC_WIFI_NAN_ENABLE),y) -scsc_wlan-$(CONFIG_SCSC_WLAN) += nl80211_vendor_nan.o -scsc_wlan-$(CONFIG_SCSC_WLAN) += mlme_nan.o -endif - -ifeq ($(CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD),y) -ccflags-y += -DCONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD -endif - -# --------------------------------------------------------------------------- -# Include -# --------------------------------------------------------------------------- -# TODO: This is only required because scsc_wifilogger is in the wrong driver directory -ccflags-y += -Idrivers/misc/samsung/scsc - -# ---------------------------------------------------------------------------- -# Wlan configuration -# ---------------------------------------------------------------------------- -ccflags-$(CONFIG_SCSC_WLAN_DEBUG) += -DCONFIG_SCSC_WLAN_DEBUG -ccflags-$(CONFIG_SCSC_WLAN_SKB_TRACKING) += -DCONFIG_SCSC_WLAN_SKB_TRACKING -ccflags-$(CONFIG_SCSC_WLAN_OFFLINE_TRACE) += -DCONFIG_SCSC_WLAN_OFFLINE_TRACE -ccflags-$(CONFIG_SCSC_WLAN_OFFLINE_DATA_PLANE_PROFILE_TRACE) += -DCONFIG_SCSC_WLAN_OFFLINE_DATA_PLANE_PROFILE_TRACE -ccflags-$(CONFIG_SCSC_WLAN_OFFLINE_TX_TRACE) += -DCONFIG_SCSC_WLAN_OFFLINE_TX_TRACE -ccflags-$(CONFIG_SCSC_WLAN_HIP_PSCHED_AMSDU) += -DCONFIG_SCSC_WLAN_HIP_PSCHED_AMSDU -ccflags-$(CONFIG_SCSC_WLAN_RX_NAPI) += -DCONFIG_SCSC_WLAN_RX_NAPI -ccflags-$(CONFIG_SCSC_WLAN_RX_NAPI_GRO) += -DCONFIG_SCSC_WLAN_RX_NAPI_GRO -ccflags-$(CONFIG_SCSC_WLAN_HIP_SUPPORT_SCATTER_GATHER_API) += -DCONFIG_SCSC_WLAN_HIP_SUPPORT_SCATTER_GATHER_API -ccflags-$(CONFIG_SCSC_WLAN_WES_NCHO) += -DCONFIG_SCSC_WLAN_WES_NCHO -ccflags-$(CONFIG_SCSC_WLAN_MUTEX_DEBUG) += -DCONFIG_SCSC_WLAN_MUTEX_DEBUG -ccflags-$(CONFIG_SCSC_WLAN_BLOCK_IPV6) += -DCONFIG_SCSC_WLAN_BLOCK_IPV6 -ccflags-$(CONFIG_SCSC_WLAN_DISABLE_NAT_KA) += -DCONFIG_SCSC_WLAN_DISABLE_NAT_KA - -ccflags-y += $(CONFIG_SAMSUNG_MAXWELL_EXTRA) -ccflags-y += -DCONFIG_SCSC_WLAN_MAX_INTERFACES=$(CONFIG_SCSC_WLAN_MAX_INTERFACES) - -# Android specific build options -ccflags-$(CONFIG_SCSC_WLAN_ANDROID) += -DCONFIG_SCSC_WLAN_ANDROID - -## See drivers/misc/samsung/scsc/ Makefile for an explanation of the reasons -## of the following ifeq/else -ifeq ($(CONFIG_SCSC_LOGRING), m) -ccflags-y += -DCONFIG_SCSC_PRINTK -else -ccflags-$(CONFIG_SCSC_LOGRING) += -DCONFIG_SCSC_PRINTK -endif diff --git a/drivers/net/wireless/scsc/acm_api.c b/drivers/net/wireless/scsc/acm_api.c deleted file mode 100755 index d64ee26ac611..000000000000 --- a/drivers/net/wireless/scsc/acm_api.c +++ /dev/null @@ -1,74 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include "mlme.h" -#include "mib.h" -#include "debug.h" -/* PSID Hdr(4) + VLDATA Hdr(1) + TSF(8) * + padding(1)*/ -#define TSF_RESP_SIZE (14) - -unsigned long long SDA_getTsf(const unsigned char if_id) -{ - struct net_device *dev = NULL; - struct netdev_vif *ndev_vif = NULL; - struct slsi_dev *sdev = NULL; - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - /* Alloc buffer in stack to avoid possible scheduling when malloc.*/ - u8 res_payload[TSF_RESP_SIZE] = { 0 }; - int r = 0; - int rx_length = 0; - unsigned long long ret = 0; - - read_lock(&dev_base_lock); - dev = first_net_device(&init_net); - while (dev) { - if (if_id == 0 && memcmp(dev->name, "wlan0", 5) == 0) - break; - else if (if_id == 1 && memcmp(dev->name, "p2p0", 4) == 0) - break; - dev = next_net_device(dev); - } - read_unlock(&dev_base_lock); - - if (!dev) { - SLSI_ERR(sdev, "dev is null\n"); - return 0; - } - ndev_vif = netdev_priv(dev); - if (!ndev_vif) { - SLSI_ERR(sdev, "ndev_vif is null\n"); - return 0; - } - sdev = ndev_vif->sdev; - if (!sdev) { - SLSI_ERR(sdev, "sdev is null\n"); - return 0; - } - - SLSI_DBG3(sdev, SLSI_MLME, "\n"); - slsi_mib_encode_get(&mibreq, SLSI_PSID_UNIFI_CURRENT_TSF_TIME, 0); - mibrsp.dataLength = sizeof(res_payload); - mibrsp.data = res_payload; - - r = slsi_mlme_get(sdev, dev, mibreq.data, mibreq.dataLength, mibrsp.data, mibrsp.dataLength, &rx_length); - - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = rx_length; - if (rx_length == 0) { - SLSI_ERR(sdev, "Mib decode error\n"); - return 0; - } - slsi_mib_decodeInt64(&mibrsp.data[4], &ret); - } else { - SLSI_ERR(sdev, "Mib read failed (error: %d)\n", r); - return 0; - } - return ret; -} diff --git a/drivers/net/wireless/scsc/ba.c b/drivers/net/wireless/scsc/ba.c deleted file mode 100755 index 3f95fa1833e5..000000000000 --- a/drivers/net/wireless/scsc/ba.c +++ /dev/null @@ -1,616 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "debug.h" -#include "dev.h" -#include "ba.h" -#include "mgt.h" - -/* Age value for frames in MPDU reorder buffer */ -static int ba_mpdu_reorder_age_timeout = 150; /* 150 milli seconds */ -module_param(ba_mpdu_reorder_age_timeout, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ba_mpdu_reorder_age_timeout, "Timeout (in ms) before a BA frame in Reorder buffer is passed to upper layers"); - -#define BA_WINDOW_BOUNDARY 2048 - -#define SN_TO_INDEX(__ba_session_rx, __sn) (((__sn - __ba_session_rx->start_sn) & 0xFFF) % __ba_session_rx->buffer_size) - -#define ADVANCE_EXPECTED_SN(__ba_session_rx) \ - { \ - __ba_session_rx->expected_sn++; \ - __ba_session_rx->expected_sn &= 0xFFF; \ - } - -#define FREE_BUFFER_SLOT(__ba_session_rx, __index) \ - { \ - __ba_session_rx->occupied_slots--; \ - __ba_session_rx->buffer[__index].active = false; \ - } - -#define IS_SN_LESS(sn1, sn2) ((((sn1) - (sn2)) & 0xFFF) > BA_WINDOW_BOUNDARY) - -void slsi_rx_ba_init(struct slsi_dev *sdev) -{ - int i; - - for (i = 0; i < SLSI_MAX_RX_BA_SESSIONS; i++) - slsi_spinlock_create(&sdev->rx_ba_buffer_pool[i].ba_lock); - - slsi_spinlock_create(&sdev->rx_ba_buffer_pool_lock); -} - -static struct slsi_ba_session_rx *slsi_rx_ba_alloc_buffer(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct slsi_ba_session_rx *buffer = NULL; - int i; - - SLSI_NET_DBG3(dev, SLSI_RX_BA, "RX BA buffer pool status: %d,%d,%d,%d,%d,%d,%d,%d\n", - sdev->rx_ba_buffer_pool[0].used, sdev->rx_ba_buffer_pool[1].used, sdev->rx_ba_buffer_pool[2].used, - sdev->rx_ba_buffer_pool[3].used, sdev->rx_ba_buffer_pool[4].used, sdev->rx_ba_buffer_pool[5].used, - sdev->rx_ba_buffer_pool[6].used, sdev->rx_ba_buffer_pool[7].used); - - slsi_spinlock_lock(&sdev->rx_ba_buffer_pool_lock); - for (i = 0; i < SLSI_MAX_RX_BA_SESSIONS; i++) { - if (!sdev->rx_ba_buffer_pool[i].used) { - sdev->rx_ba_buffer_pool[i].used = true; - buffer = &sdev->rx_ba_buffer_pool[i]; - break; - } - } - slsi_spinlock_unlock(&sdev->rx_ba_buffer_pool_lock); - - if (!buffer) - SLSI_NET_ERR(dev, "No free RX BA buffer\n"); - - return buffer; -} - -static void slsi_rx_ba_free_buffer(struct net_device *dev, struct slsi_peer *peer, int tid) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - - slsi_spinlock_lock(&sdev->rx_ba_buffer_pool_lock); - if (peer && peer->ba_session_rx[tid]) { - peer->ba_session_rx[tid]->used = false; - peer->ba_session_rx[tid] = NULL; - } - slsi_spinlock_unlock(&sdev->rx_ba_buffer_pool_lock); - - SLSI_NET_DBG3(dev, SLSI_RX_BA, "RX BA buffer pool status: %d,%d,%d,%d,%d,%d,%d,%d\n", - sdev->rx_ba_buffer_pool[0].used, sdev->rx_ba_buffer_pool[1].used, sdev->rx_ba_buffer_pool[2].used, - sdev->rx_ba_buffer_pool[3].used, sdev->rx_ba_buffer_pool[4].used, sdev->rx_ba_buffer_pool[5].used, - sdev->rx_ba_buffer_pool[6].used, sdev->rx_ba_buffer_pool[7].used); -} - -/* This code - slsi_ba_process_complete() - * is called in the data workqueue context with the - * netdev_vif mutex held. - */ -void slsi_ba_process_complete(struct net_device *dev, bool from_ba_timer) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *skb; - - while ((skb = slsi_skb_dequeue(&ndev_vif->ba_complete)) != NULL) - slsi_rx_data_deliver_skb(ndev_vif->sdev, dev, skb, from_ba_timer); -} - -static void slsi_ba_signal_process_complete(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - struct slsi_dev *sdev = ndev_vif->sdev; - u32 conf_hip4_ver = 0; -#endif - - atomic_set(&ndev_vif->ba_flush, 1); -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); - if (conf_hip4_ver == 5) - slsi_skb_schedule_work(&ndev_vif->rx_data); -#else - slsi_skb_schedule_work(&ndev_vif->rx_data); -#endif -} - -static void ba_add_frame_to_ba_complete(struct net_device *dev, struct slsi_ba_frame_desc *frame_desc) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - slsi_skb_queue_tail(&ndev_vif->ba_complete, frame_desc->signal); -} - -static void ba_update_expected_sn(struct net_device *dev, - struct slsi_ba_session_rx *ba_session_rx, u16 sn) -{ - u32 i, j; - u16 gap; - - gap = (sn - ba_session_rx->expected_sn) & 0xFFF; - SLSI_NET_DBG3(dev, SLSI_RX_BA, "Proccess the frames up to new expected_sn = %d gap = %d\n", sn, gap); - - for (j = 0; j < gap && j < ba_session_rx->buffer_size; j++) { - i = SN_TO_INDEX(ba_session_rx, ba_session_rx->expected_sn); - SLSI_NET_DBG3(dev, SLSI_RX_BA, "Proccess the slot index = %d\n", i); - if (ba_session_rx->buffer[i].active) { - ba_add_frame_to_ba_complete(dev, &ba_session_rx->buffer[i]); - SLSI_NET_DBG3(dev, SLSI_RX_BA, "Proccess the frame at index = %d expected_sn = %d\n", i, ba_session_rx->expected_sn); - FREE_BUFFER_SLOT(ba_session_rx, i); - } else { - SLSI_NET_DBG3(dev, SLSI_RX_BA, "Empty slot at index = %d\n", i); - } - ADVANCE_EXPECTED_SN(ba_session_rx); - } - ba_session_rx->expected_sn = sn; -} - -static void ba_complete_ready_sequence(struct net_device *dev, - struct slsi_ba_session_rx *ba_session_rx) -{ - int i; - - i = SN_TO_INDEX(ba_session_rx, ba_session_rx->expected_sn); - while (ba_session_rx->buffer[i].active) { - ba_add_frame_to_ba_complete(dev, &ba_session_rx->buffer[i]); - SLSI_NET_DBG4(dev, SLSI_RX_BA, "Completed stored frame (expected_sn=%d) at i = %d\n", - ba_session_rx->expected_sn, i); - FREE_BUFFER_SLOT(ba_session_rx, i); - ADVANCE_EXPECTED_SN(ba_session_rx); - i = SN_TO_INDEX(ba_session_rx, ba_session_rx->expected_sn); - } -} - -static void ba_scroll_window(struct net_device *dev, - struct slsi_ba_session_rx *ba_session_rx, u16 sn) -{ - if (((sn - ba_session_rx->expected_sn) & 0xFFF) <= BA_WINDOW_BOUNDARY) { - ba_update_expected_sn(dev, ba_session_rx, sn); - ba_complete_ready_sequence(dev, ba_session_rx); - } -} - -static int ba_consume_frame_or_get_buffer_index(struct net_device *dev, struct slsi_peer *peer, - struct slsi_ba_session_rx *ba_session_rx, u16 sn, struct slsi_ba_frame_desc *frame_desc, bool *stop_timer) -{ - int i; - u16 sn_temp; -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - struct netdev_vif *ndev_vif = netdev_priv(dev); -#endif - - *stop_timer = false; - - if (((sn - ba_session_rx->expected_sn) & 0xFFF) <= BA_WINDOW_BOUNDARY) { - /* Once we are in BA window, set the flag for BA trigger */ - if (!ba_session_rx->trigger_ba_after_ssn) - ba_session_rx->trigger_ba_after_ssn = true; - - sn_temp = ba_session_rx->expected_sn + ba_session_rx->buffer_size; - SLSI_NET_DBG4(dev, SLSI_RX_BA, "New frame: sn=%d\n", sn); - - if (!(((sn - sn_temp) & 0xFFF) > BA_WINDOW_BOUNDARY)) { - u16 new_expected_sn; - - SLSI_NET_DBG2(dev, SLSI_RX_BA, "Frame is out of window\n"); - sn_temp = (sn - ba_session_rx->buffer_size) & 0xFFF; - if (ba_session_rx->timer_on) - *stop_timer = true; - new_expected_sn = (sn_temp + 1) & 0xFFF; - ba_update_expected_sn(dev, ba_session_rx, new_expected_sn); - } - - i = -1; - if (sn == ba_session_rx->expected_sn) { - SLSI_NET_DBG4(dev, SLSI_RX_BA, "sn = ba_session_rx->expected_sn = %d\n", sn); - if (ba_session_rx->timer_on) - *stop_timer = true; - ADVANCE_EXPECTED_SN(ba_session_rx); - ba_add_frame_to_ba_complete(dev, frame_desc); - } else { - i = SN_TO_INDEX(ba_session_rx, sn); - SLSI_NET_DBG4(dev, SLSI_RX_BA, "sn (%d) != ba_session_rx->expected_sn(%d), i = %d\n", sn, ba_session_rx->expected_sn, i); - if (ba_session_rx->buffer[i].active) { - SLSI_NET_DBG3(dev, SLSI_RX_BA, "free frame at i = %d\n", i); - i = -1; - slsi_kfree_skb(frame_desc->signal); - } - } - if (!IS_SN_LESS(sn, ba_session_rx->highest_received_sn)) - ba_session_rx->highest_received_sn = sn; - } else { - i = -1; - if (!ba_session_rx->trigger_ba_after_ssn) { - SLSI_NET_DBG3(dev, SLSI_RX_BA, "frame before ssn, pass it up: sn=%d\n", sn); - ba_add_frame_to_ba_complete(dev, frame_desc); - } else { - if (slsi_is_tdls_peer(dev, peer)) { - /* Don't drop old frames in TDLS AMPDU-reordering for interoperability with third party devices. - * When the TDLS link is established the peer sends few packets with AP's sequence number. - * BA reorder logic updates the expected sequence number. After that peer sends packets with - * starting sequence number negotiated in BA (0). But those frames are getting dropped here. - * Because of this TCP traffic does not work and TDLS link is getting disconnected. - */ - SLSI_NET_DBG1(dev, SLSI_RX_BA, "tdls: forward old frame: sn=%d, expected_sn=%d\n", sn, ba_session_rx->expected_sn); - ba_add_frame_to_ba_complete(dev, frame_desc); - } else { - /* this frame is deemed as old. But it may so happen that the reorder process did not wait long - * enough for this frame and moved to new window. So check here that the current frame still lies in - * originators transmit window by comparing it with highest sequence number received from originator. - * - * If it lies in the window pass the frame to next process else discard the frame here. - */ - if (IS_SN_LESS(ba_session_rx->highest_received_sn, (((sn + ba_session_rx->buffer_size) & 0xFFF) - 1))) { - SLSI_NET_DBG4(dev, SLSI_RX_BA, "old frame, but still in window: sn=%d, highest_received_sn=%d\n", sn, ba_session_rx->highest_received_sn); - ba_add_frame_to_ba_complete(dev, frame_desc); - } else { - SLSI_NET_DBG1(dev, SLSI_RX_BA, "old frame, drop: sn=%d, expected_sn=%d\n", sn, ba_session_rx->expected_sn); -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - if (ndev_vif->enhanced_arp_detect_enabled) - slsi_fill_enhanced_arp_out_of_order_drop_counter(ndev_vif, - frame_desc->signal); -#endif - slsi_kfree_skb(frame_desc->signal); - } - } - } - } - return i; -} - -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE -static void slsi_ba_aging_timeout_handler(struct timer_list *t) -#else -static void slsi_ba_aging_timeout_handler(unsigned long data) -#endif -{ -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - struct slsi_ba_session_rx *ba_session_rx = from_timer(ba_session_rx, t, ba_age_timer); -#else - struct slsi_ba_session_rx *ba_session_rx = (struct slsi_ba_session_rx *)data; -#endif - u8 i, j; - u8 gap = 1; - u16 temp_sn; - struct net_device *dev = ba_session_rx->dev; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - u32 conf_hip4_ver = 0; -#endif - - SLSI_NET_DBG3(dev, SLSI_RX_BA, "\n"); - - slsi_spinlock_lock(&ba_session_rx->ba_lock); - - ba_session_rx->timer_on = false; - - if (ba_session_rx->active && ba_session_rx->occupied_slots) { - /* expected sequence has not arrived so start searching from next - * sequence number until a frame is available and determine the gap. - * Release all the frames upto next hole from the reorder buffer. - */ - temp_sn = (ba_session_rx->expected_sn + 1) & 0xFFF; - - for (j = 0; j < ba_session_rx->buffer_size; j++) { - i = SN_TO_INDEX(ba_session_rx, temp_sn); - - if (ba_session_rx->buffer[i].active) { - while (gap--) - ADVANCE_EXPECTED_SN(ba_session_rx); - - SLSI_NET_DBG3(dev, SLSI_RX_BA, "Completed stored frame (expected_sn=%d) at i = %d\n", ba_session_rx->expected_sn, i); - ba_add_frame_to_ba_complete(dev, &ba_session_rx->buffer[i]); - FREE_BUFFER_SLOT(ba_session_rx, i); - ADVANCE_EXPECTED_SN(ba_session_rx); - ba_complete_ready_sequence(dev, ba_session_rx); - break; - } - /* advance temp sequence number and frame gap */ - temp_sn = (temp_sn + 1) & 0xFFF; - gap++; - } - - /* Check for next hole in the buffer, if hole exists create the timer for next missing frame */ - if (ba_session_rx->occupied_slots) { - SLSI_NET_DBG3(dev, SLSI_RX_BA, "Timer start\n"); - mod_timer(&ba_session_rx->ba_age_timer, jiffies + msecs_to_jiffies(ba_mpdu_reorder_age_timeout)); - ba_session_rx->timer_on = true; - } - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - /* Process the data now marked as completed */ -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); - if (conf_hip4_ver == 4) - slsi_ba_process_complete(dev, true); - else - slsi_ba_signal_process_complete(dev); -#else - slsi_ba_signal_process_complete(dev); -#endif - } else { - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - } -} - -int slsi_ba_process_frame(struct net_device *dev, struct slsi_peer *peer, - struct sk_buff *skb, u16 sequence_number, u16 tid) -{ - int i; - struct slsi_ba_session_rx *ba_session_rx = peer->ba_session_rx[tid]; - struct slsi_ba_frame_desc frame_desc; - bool stop_timer = false; - - SLSI_NET_DBG4(dev, SLSI_RX_BA, "Got frame(sn=%d)\n", sequence_number); - - if (WARN_ON(tid > FAPI_PRIORITY_QOS_UP7)) { - SLSI_NET_ERR(dev, "tid=%d\n", tid); - return -EINVAL; - } - - if (!ba_session_rx) - return -EINVAL; - - slsi_spinlock_lock(&ba_session_rx->ba_lock); - - if (!ba_session_rx->active) { - SLSI_NET_ERR(dev, "No BA session exists\n"); - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - return -EINVAL; - } - - frame_desc.signal = skb; - frame_desc.sn = sequence_number; - frame_desc.active = true; - - i = ba_consume_frame_or_get_buffer_index(dev, peer, ba_session_rx, sequence_number, &frame_desc, &stop_timer); - if (i >= 0) { - SLSI_NET_DBG4(dev, SLSI_RX_BA, "Store frame(sn=%d) at i = %d\n", sequence_number, i); - ba_session_rx->buffer[i] = frame_desc; - ba_session_rx->occupied_slots++; - } else { - SLSI_NET_DBG4(dev, SLSI_RX_BA, "Frame consumed - sn = %d\n", sequence_number); - } - - ba_complete_ready_sequence(dev, ba_session_rx); - - /* Timer decision: - * - * If the timer is not running (timer_on=false) - * Start the timer if there are holes (occupied_slots!=0) - * - * If the timer is running (timer_on=true) - * Stop the timer if - * There are no holes (occupied_slots=0) - * Restart the timer if - * stop_timer=true and there are holes (occupied_slots!=0) - * Leave the timer running (do nothing) if - * stop_timer=false and there are holes (occupied_slots!=0) - */ - - if (!ba_session_rx->timer_on) { - if (ba_session_rx->occupied_slots) { - stop_timer = false; - SLSI_NET_DBG4(dev, SLSI_RX_BA, "Timer start\n"); - mod_timer(&ba_session_rx->ba_age_timer, jiffies + msecs_to_jiffies(ba_mpdu_reorder_age_timeout)); - ba_session_rx->timer_on = true; - } - } else if (!ba_session_rx->occupied_slots) { - stop_timer = true; - } else if (stop_timer) { - stop_timer = false; - SLSI_NET_DBG4(dev, SLSI_RX_BA, "Timer restart\n"); - mod_timer(&ba_session_rx->ba_age_timer, jiffies + msecs_to_jiffies(ba_mpdu_reorder_age_timeout)); - ba_session_rx->timer_on = true; - } - - if (stop_timer) { - ba_session_rx->timer_on = false; - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - SLSI_NET_DBG4(dev, SLSI_RX_BA, "Timer stop\n"); - del_timer_sync(&ba_session_rx->ba_age_timer); - } else { - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - } - slsi_ba_signal_process_complete(dev); - return 0; -} - -bool slsi_ba_check(struct slsi_peer *peer, u16 tid) -{ - if (tid > FAPI_PRIORITY_QOS_UP7) - return false; - if (!peer->ba_session_rx[tid]) - return false; - - return peer->ba_session_rx[tid]->active; -} - -static void __slsi_rx_ba_stop(struct net_device *dev, struct slsi_ba_session_rx *ba_session_rx) -{ - u8 i, j; - - SLSI_NET_DBG1(dev, SLSI_RX_BA, "Stopping BA session: tid = %d\n", ba_session_rx->tid); - - if (WARN_ON(!ba_session_rx->active)) { - SLSI_NET_ERR(dev, "No BA session exists\n"); - return; - } - - for (i = SN_TO_INDEX(ba_session_rx, ba_session_rx->expected_sn), j = 0; - j < ba_session_rx->buffer_size; i++, j++) { - i %= ba_session_rx->buffer_size; - if (ba_session_rx->buffer[i].active) { - ba_add_frame_to_ba_complete(dev, &ba_session_rx->buffer[i]); - SLSI_NET_DBG3(dev, SLSI_RX_BA, "Completed stored frame at i = %d\n", i); - FREE_BUFFER_SLOT(ba_session_rx, i); - } - } - ba_session_rx->active = false; -} - -static void slsi_rx_ba_stop_lock_held(struct net_device *dev, struct slsi_ba_session_rx *ba_session_rx) -{ - __slsi_rx_ba_stop(dev, ba_session_rx); - if (ba_session_rx->timer_on) { - ba_session_rx->timer_on = false; - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - del_timer_sync(&ba_session_rx->ba_age_timer); - slsi_spinlock_lock(&ba_session_rx->ba_lock); - } -} - -static void slsi_rx_ba_stop_lock_unheld(struct net_device *dev, struct slsi_ba_session_rx *ba_session_rx) -{ - slsi_spinlock_lock(&ba_session_rx->ba_lock); - __slsi_rx_ba_stop(dev, ba_session_rx); - if (ba_session_rx->timer_on) { - ba_session_rx->timer_on = false; - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - del_timer_sync(&ba_session_rx->ba_age_timer); - } else { - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - } -} - -void slsi_rx_ba_stop_all(struct net_device *dev, struct slsi_peer *peer) -{ - int i; - - for (i = 0; i < NUM_BA_SESSIONS_PER_PEER; i++) - if (peer->ba_session_rx[i] && peer->ba_session_rx[i]->active) { - slsi_rx_ba_stop_lock_unheld(dev, peer->ba_session_rx[i]); - slsi_rx_ba_free_buffer(dev, peer, i); - } -} - -static int slsi_rx_ba_start(struct net_device *dev, - struct slsi_ba_session_rx *ba_session_rx, - u16 tid, u16 buffer_size, u16 start_sn) -{ - SLSI_NET_DBG1(dev, SLSI_RX_BA, "Request to start a new BA session tid=%d buffer_size=%d start_sn=%d\n", - tid, buffer_size, start_sn); - - if (WARN_ON((!buffer_size) || (buffer_size > SLSI_BA_BUFFER_SIZE_MAX))) { - SLSI_NET_ERR(dev, "Invalid window size: buffer_size=%d\n", buffer_size); - return -EINVAL; - } - - slsi_spinlock_lock(&ba_session_rx->ba_lock); - - if (ba_session_rx->active) { - SLSI_NET_DBG1(dev, SLSI_RX_BA, "BA session already exists\n"); - - if ((ba_session_rx->buffer_size == buffer_size) && - (ba_session_rx->expected_sn == start_sn)) { - SLSI_NET_DBG1(dev, SLSI_RX_BA, - "BA session tid=%d already exists. The parameters match so keep the existing session\n", - tid); - - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - - return 0; - } - SLSI_NET_DBG1(dev, SLSI_RX_BA, "Parameters don't match so stop the existing BA session: tid=%d\n", tid); - slsi_rx_ba_stop_lock_held(dev, ba_session_rx); - } - - ba_session_rx->dev = dev; - ba_session_rx->buffer_size = buffer_size; - ba_session_rx->start_sn = start_sn; - ba_session_rx->expected_sn = start_sn; - ba_session_rx->highest_received_sn = 0; - ba_session_rx->trigger_ba_after_ssn = false; - ba_session_rx->tid = tid; - ba_session_rx->timer_on = false; -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - timer_setup(&ba_session_rx->ba_age_timer, slsi_ba_aging_timeout_handler, 0); -#else - ba_session_rx->ba_age_timer.function = slsi_ba_aging_timeout_handler; - ba_session_rx->ba_age_timer.data = (unsigned long)ba_session_rx; - init_timer(&ba_session_rx->ba_age_timer); -#endif - - ba_session_rx->active = true; - SLSI_NET_DBG1(dev, SLSI_RX_BA, "Started a new BA session tid=%d buffer_size=%d start_sn=%d\n", - tid, buffer_size, start_sn); - - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - slsi_ba_signal_process_complete(dev); - - return 0; -} - -static void slsi_ba_process_error(struct net_device *dev, - struct slsi_ba_session_rx *ba_session_rx, u16 sequence_number) -{ - slsi_spinlock_lock(&ba_session_rx->ba_lock); - - if (WARN_ON(!ba_session_rx->active)) { - SLSI_NET_ERR(dev, "No BA session exists\n"); - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - return; - } - - ba_scroll_window(dev, ba_session_rx, sequence_number); - - slsi_spinlock_unlock(&ba_session_rx->ba_lock); - slsi_ba_signal_process_complete(dev); -} - -void slsi_handle_blockack(struct net_device *dev, struct slsi_peer *peer, - u16 vif, u8 *peer_qsta_address, u16 parameter_set, u16 sequence_number, - u16 reason_code, u16 direction) -{ - struct slsi_ba_session_rx *ba_session_rx; - u16 user_priority = (parameter_set >> 2) & 0x000F; - u16 buffer_size = (parameter_set >> 6) & 0x03FF; - - SLSI_UNUSED_PARAMETER(vif); - SLSI_UNUSED_PARAMETER(peer_qsta_address); - - if (WARN_ON(user_priority > FAPI_PRIORITY_QOS_UP7)) { - SLSI_NET_ERR(dev, "Invalid user_priority=%d\n", user_priority); - return; - } - - switch (direction) { - case FAPI_DIRECTION_TRANSMIT: - break; - case FAPI_DIRECTION_RECEIVE: - ba_session_rx = peer->ba_session_rx[user_priority]; - - switch (reason_code) { - case FAPI_REASONCODE_START: - if (!peer->ba_session_rx[user_priority]) - peer->ba_session_rx[user_priority] = slsi_rx_ba_alloc_buffer(dev); - - if (peer->ba_session_rx[user_priority]) - if (slsi_rx_ba_start(dev, peer->ba_session_rx[user_priority], user_priority, buffer_size, sequence_number) != 0) - slsi_rx_ba_free_buffer(dev, peer, user_priority); - break; - case FAPI_REASONCODE_END: - if (ba_session_rx) { - slsi_rx_ba_stop_lock_unheld(dev, ba_session_rx); - slsi_rx_ba_free_buffer(dev, peer, user_priority); - } - break; - case FAPI_REASONCODE_UNSPECIFIED_REASON: - if (ba_session_rx) - slsi_ba_process_error(dev, ba_session_rx, sequence_number); - break; - default: - SLSI_NET_ERR(dev, "Invalid value: reason_code=%d\n", reason_code); - break; - } - break; - default: - SLSI_NET_ERR(dev, "Invalid value: direction=%d\n", direction); - break; - } -} diff --git a/drivers/net/wireless/scsc/ba.h b/drivers/net/wireless/scsc/ba.h deleted file mode 100755 index af442233ad7a..000000000000 --- a/drivers/net/wireless/scsc/ba.h +++ /dev/null @@ -1,26 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_BA_H__ -#define __SLSI_BA_H__ - -#include "dev.h" - -void slsi_handle_blockack(struct net_device *dev, struct slsi_peer *peer, - u16 vif, u8 *peer_qsta_address, u16 parameter_set, u16 sequence_number, - u16 reason_code, u16 direction); - -int slsi_ba_process_frame(struct net_device *dev, struct slsi_peer *peer, - struct sk_buff *skb, u16 sequence_number, u16 tid); - -void slsi_ba_process_complete(struct net_device *dev, bool from_ba_timer); - -bool slsi_ba_check(struct slsi_peer *peer, u16 tid); - -void slsi_rx_ba_stop_all(struct net_device *dev, struct slsi_peer *peer); - -void slsi_rx_ba_init(struct slsi_dev *sdev); -#endif diff --git a/drivers/net/wireless/scsc/cac.c b/drivers/net/wireless/scsc/cac.c deleted file mode 100755 index 70abc0471978..000000000000 --- a/drivers/net/wireless/scsc/cac.c +++ /dev/null @@ -1,1487 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "cac.h" - -static struct cac_tspec *tspec_list; -static int tspec_list_next_id; -static u8 dialog_token_next; - -/* Define the meta-data info for tspec_fields */ -static struct tspec_field tspec_fields[] = { - { "traffic_type", 0, 1, 0x1, 0 }, - { "tsid", 0, 1, 0xF, 1 }, - { "direction", 0, 1, 0x3, 5 }, - { "access_policy", 0, 1, 0x3, 7 }, /* WMM - always set to 1 */ - { "aggregation", 0, 1, 0x1, 9 }, /* WMM - not supported */ - { "psb", 0, 1, 0x1, 10 }, - { "user_priority", 0, 1, 0x7, 11 }, - { "tsinfo_ack_policy", 0, 1, 0x3, 14 }, /* WMM - not supported */ - { "schedule", 0, 1, 0x1, 16 }, /* WMM - not supported */ - { "nominal_msdu_size", 0, 0, 2, OFFSETOF(nominal_msdu_size) }, - { "max_msdu_size", 0, 0, 2, OFFSETOF(maximum_msdu_size) }, - { "min_service_interval", 0, 0, 4, OFFSETOF(minimum_service_interval) }, - { "max_service_interval", 0, 0, 4, OFFSETOF(maximum_service_interval) }, - { "inactivity_interval", 0, 0, 4, OFFSETOF(inactivity_interval) }, - { "suspension_interval", 0, 0, 4, OFFSETOF(suspension_interval) }, - { "service_start_time", 0, 0, 4, OFFSETOF(service_start_time) }, - { "min_data_rate", 0, 0, 4, OFFSETOF(minimum_data_rate) }, - { "mean_data_rate", 0, 0, 4, OFFSETOF(mean_data_rate) }, - { "peak_data_rate", 0, 0, 4, OFFSETOF(peak_data_rate) }, - { "max_burst_size", 0, 0, 4, OFFSETOF(maximum_burst_size) }, - { "delay_bound", 0, 0, 4, OFFSETOF(delay_bound) }, - { "min_phy_rate", 0, 0, 4, OFFSETOF(minimum_phy_rate) }, - { "surplus_bw_allowance", 0, 0, 2, - OFFSETOF(surplus_bandwidth_allowance) }, - { "medium_time", 0, 0, 2, OFFSETOF(medium_time) }, -}; - -/* Define the OUI type data for the corresponding IE's */ -static const u8 TSRS_OUI_TYPE[] = { 0x00, 0x40, 0x96, 0x08 }; -static const u8 EBW_OUI_TYPE[] = { 0x00, 0x40, 0x96, 0x0F }; - -static const int NUM_TSPEC_FIELDS = sizeof(tspec_fields) / sizeof(struct tspec_field); -static u32 previous_msdu_lifetime = MAX_TRANSMIT_MSDU_LIFETIME_NOT_VALID; -static u8 ccx_status = BSS_CCX_DISABLED; - -static void cac_set_ric_ie(struct slsi_dev *sdev, struct net_device *netdev); -static int cac_get_rde_tspec_ie(struct slsi_dev *sdev, u8 *assoc_rsp_ie, int assoc_rsp_ie_len, const u8 **tspec_ie_arr); -/* Name: strtoint - * Desc: Converts a string to a decimal or hexadecimal integer - * s: the string to be converted - * res: pointer to the calculated integer - * return: 0 (success), 1(failure) - */ -static int strtoint(const char *s, int *res) -{ - int base = 10; - - if (strlen(s) > 2) - if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) - base = 16; - return kstrtoint(s, base, res); -} - -/* Name: find_tspec_entry - * Desc: Finds a tspec entry in the list of tspecs (tspec_list) - * according to tspec id and status (accepted or not accepted) - * id: the tspec id - * accepted: 1 : accepted by AP, 0: new or rejected by AP - * return: pointer to the tspec struct or NULL if a tspec doesn't exist - */ -static struct cac_tspec *find_tspec_entry(int id, int accepted) -{ - struct cac_tspec *itr; - - itr = tspec_list; - while (itr != NULL) { - if ((itr->id == id) && (itr->accepted == accepted)) - break; - itr = itr->next; - } - return itr; -} - -/* Name: cac_query_tspec_field - * Desc: Get the value of a tspec's field. - * sdev: pointer to the slsi_dev struct - * entry: pointer to the tspec - * field: the field name - * value: poinet to the field value - * return: 0 (success), -1 (failure) - */ -static int cac_query_tspec_field(struct slsi_dev *sdev, struct cac_tspec *entry, const char *field, u32 *value) -{ - int i; - u32 tsinfo; - u8 mask; - u8 *pos; - - if ((entry == NULL) || (field == NULL) || (value == NULL)) - return -1; - - for (i = 0; i < NUM_TSPEC_FIELDS; i++) - if (strcasecmp(field, tspec_fields[i].name) == 0) - break; - if (i >= NUM_TSPEC_FIELDS) { - SLSI_ERR(sdev, "CAC: Invalid TSPEC config field\n"); - return -1; - } - if (tspec_fields[i].is_tsinfo_field) { - mask = tspec_fields[i].size; - tsinfo = CAC_GET_LE24(&entry->tspec.ts_info[0]) & TSINFO_MASK; - *value = (tsinfo >> tspec_fields[i].offset) & mask; - } else { - pos = (u8 *)(&entry->tspec) + tspec_fields[i].offset; - if (tspec_fields[i].size == 1) - *value = (*pos & 0xFF); - else if (tspec_fields[i].size == 2) - *value = CAC_GET_LE16(pos); - else - *value = CAC_GET_LE32(pos); - } - - return 0; -} - -/* Name: get_netdev_for_station - * Desc: Get the pointer to net_device struct with vif_type == FAPI_VIFTYPE_STATION - * sdev: pointer to the slsi_dev struct - * return: pointer to the net_device struct or NULL if the it doesn't exist - */ -static struct net_device *get_netdev_for_station(struct slsi_dev *sdev) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - s32 vif; - - for (vif = 1; vif <= CONFIG_SCSC_WLAN_MAX_INTERFACES; vif++) { - dev = slsi_get_netdev_locked(sdev, vif); - if (!dev) - continue; - ndev_vif = netdev_priv(dev); - if (!ndev_vif) - continue; - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION && - ndev_vif->iftype == NL80211_IFTYPE_STATION) - return dev; - } - return NULL; -} - -/* Name: add_ebw_ie - * Desc: Add ebw ie - * buf: pointer to buf that the ie is going to added - * buf_len: the byte length of the ie - * tsid: tspec id - * return: length of bytes that were added - */ -static int add_ebw_ie(u8 *buf, size_t buf_len, u8 tsid) -{ - u8 *pos; - - if ((buf == NULL) || (buf_len < 8)) - return -1; - - pos = buf; - *pos++ = WLAN_EID_VENDOR_SPECIFIC; /* element id */ - *pos++ = 6; /* length */ - memcpy(pos, EBW_OUI_TYPE, sizeof(EBW_OUI_TYPE)); - pos += sizeof(EBW_OUI_TYPE); - *pos++ = tsid; - *pos++ = 0; - - return pos - buf; -} - -/* Name: add_tsrs_ie - * Desc: Add tsrs_ie - * buf: pointer to buf that the ie is going to added - * buf_len: the byte length of the ie - * tsid: tspec id - * rates: list of rates that are supported - * num_rates: number of rates that are supported - * return: length of bytes that were added - */ -static int add_tsrs_ie(u8 *buf, size_t buf_len, u8 tsid, - u8 rates[CCX_MAX_NUM_RATES], int num_rates) -{ - u8 *pos; - size_t ie_len = (size_t)(7 + num_rates); - int i; - - if ((buf == NULL) || (buf_len < ie_len) || (rates == NULL) || - (num_rates > CCX_MAX_NUM_RATES)) - return -1; - - pos = buf; - memset(pos, 0, ie_len); - *pos++ = WLAN_EID_VENDOR_SPECIFIC; /* element id */ - *pos++ = ie_len - 2; /* length */ - memcpy(pos, TSRS_OUI_TYPE, sizeof(TSRS_OUI_TYPE)); - pos += sizeof(TSRS_OUI_TYPE); - *pos++ = tsid; - for (i = 0; i < num_rates; i++) - *pos++ = rates[i]; - - return pos - buf; -} - -/* Name: bss_get_ie - * Desc: Get the buffer of an IE that is included in a bss - * bss: pointer to the cfg80211_bss struct - * ie: the IE id that is going to be extracted - * return: pointer to the start of the IE buffer - */ -static const u8 *bss_get_ie(struct cfg80211_bss *bss, u8 ie) -{ - const u8 *pos; - u8 ies_len, ies_cur_len; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) - pos = (const u8 *)(bss->ies); - ies_len = (u8)bss->ies->len; -#else - pos = (const u8 *)(bss->information_elements); - ies_len = (u8)bss->len_information_elements; -#endif - ies_cur_len = 1; - - while (ies_cur_len <= ies_len) { - if (pos[0] == ie) - return pos; - - pos += 2 + pos[1]; - ies_cur_len++; - } - - return NULL; -} - -/* Name: bss_get_bit_rates - * Desc: Get the buffer of an IE that is included in a bss - * bss: pointer to the cfg80211_bss struct - * rates: the rates that are supported - * return: 0 (succes), -1 (failure) - */ -static int bss_get_bit_rates(struct cfg80211_bss *bss, u8 **rates) -{ - const u8 *ie, *ie2; - int i, j; - unsigned int len; - u8 *r; - - ie = bss_get_ie(bss, WLAN_EID_SUPP_RATES); - ie2 = bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES); - - len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0); - - if (!len) - return -1; - - r = kmalloc(len, GFP_KERNEL); - if (!r) - return -1; - - for (i = 0; ie && i < ie[1]; i++) - r[i] = ie[i + 2] & 0x7f; - - for (j = 0; ie2 && j < ie2[1]; j++) - r[i + j] = ie2[j + 2] & 0x7f; - - *rates = r; - return len; -} - -/* Name: cac_send_addts - * Desc: Build and send the ADDTS action frame - * sdev: pointer to the slsi_dev struct - * id: the tspec id that is going to be included in the ADDTS action frame - * ebw: 1 (add ebw IE), 0 (don't add ebw IE) - * return: 0 (succes), -1 (failure) - */ -static int cac_send_addts(struct slsi_dev *sdev, int id, int ebw) -{ - struct action_addts_req *req; - size_t extra_ie_len = 50; - int ie_len = 0; - size_t req_len; - struct cac_tspec *entry; - u8 tsid, i; - u8 *rates; - u8 rate = 0; - u8 *pos; - int num_rates; - struct netdev_vif *ndev_vif; - struct net_device *netdev; - u16 host_tag = slsi_tx_mgmt_host_tag(sdev); - struct ieee80211_hdr *hdr; - u8 *buf = NULL; - u8 *bssid; - u8 r = 0; - - entry = find_tspec_entry(id, 0); - if (entry == NULL) { - SLSI_ERR(sdev, "CAC-ADDTS: Invalid TSPEC ID\n"); - return -1; - } - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - netdev = get_netdev_for_station(sdev); - if (netdev == NULL) { - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -1; - } - ndev_vif = netdev_priv(netdev); - if ((ndev_vif == NULL) || (ndev_vif->sta.sta_bss == NULL)) { - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -1; - } - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_ERR(sdev, "CAC-ADDTS: Not connected, can't send ADDTS\n"); - r = -1; - goto exit; - } - bssid = ndev_vif->sta.sta_bss->bssid; - if (entry->accepted) { - SLSI_ERR(sdev, "CAC-ADDTS: TSPEC already accepted\n"); - r = -1; - goto exit; - } - - buf = kmalloc(IEEE80211_HEADER_SIZE + sizeof(*req) + extra_ie_len, GFP_KERNEL); - if (buf == NULL) { - SLSI_ERR(sdev, "CAC-ADDTS: Failed to allocate ADDTS request\n"); - r = -1; - goto exit; - } - - hdr = (struct ieee80211_hdr *)buf; - hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, IEEE80211_STYPE_ACTION); - SLSI_ETHER_COPY(hdr->addr1, bssid); - SLSI_ETHER_COPY(hdr->addr2, sdev->hw_addr); - SLSI_ETHER_COPY(hdr->addr3, bssid); - - req = (struct action_addts_req *)(buf + IEEE80211_HEADER_SIZE); - req->hdr.category = WLAN_CATEGORY_WMM; - req->hdr.action = WMM_ACTION_CODE_ADDTS_REQ; - if (dialog_token_next == 0) - dialog_token_next++; - req->hdr.dialog_token = dialog_token_next++; - req->hdr.status_code = 0; - tsid = (CAC_GET_LE24(req->tspec.ts_info) >> 1) & 0xF; - - /* Find the value of PSB in TSPEC. If PSB is unspecified; fill the - * value from UAPSD value stored in Peer structure for the AC - */ - if (entry->psb_specified == 0) { - struct slsi_peer *peer; - u32 priority; - - peer = slsi_get_peer_from_qs(sdev, netdev, SLSI_STA_PEER_QUEUESET); - if (!peer) { - SLSI_ERR(sdev, "CAC-ADDTS: no Peer found\n"); - r = -1; - goto exit_free_buf; - } - - cac_query_tspec_field(sdev, entry, "user_priority", &priority); - if (peer->uapsd & BIT(slsi_frame_priority_to_ac_queue(priority))) - entry->tspec.ts_info[1] |= 0x04; - } - memcpy(&req->tspec, &entry->tspec, sizeof(entry->tspec)); - req_len = sizeof(*req); - pos = (u8 *)(req + 1); - entry->ebw = ebw ? 1 : 0; - - if (ebw) { - ie_len += add_ebw_ie(pos, extra_ie_len, tsid); - if (ie_len <= 0) - SLSI_ERR(sdev, "CAC-ADDTS: Failed to add EBW IE\n"); - } - - /* Add tsrs IE in case of ccx enabled bss */ - if (ccx_status == BSS_CCX_ENABLED) { - num_rates = bss_get_bit_rates(ndev_vif->sta.sta_bss, &rates); - if (num_rates <= 0) - rate = 12; /* Default to 6Mbps */ - else { - for (i = 0; i < num_rates; i++) - if ((rates[i] > rate) && (rates[i] <= 48)) - rate = rates[i]; - kfree(rates); - } - - do { - /* if the nominal rate is equal to minimum_phy_rate - * don't add the tsrs_ie - */ - if ((rate * TSRS_RATE_PER_UNIT) == req->tspec.minimum_phy_rate) - break; - - if ((rate * TSRS_RATE_PER_UNIT) > req->tspec.minimum_phy_rate) { - ie_len += add_tsrs_ie(pos + ie_len, extra_ie_len - ie_len, - tsid, &rate, 1); - if (ie_len <= 0) { - SLSI_ERR(sdev, "CAC-ADDTS: Failed to add TSRS IE\n"); - r = -1; - goto exit_free_buf; - } - } else { /* only the "<" case is possible */ - SLSI_ERR(sdev, "CAC-ADDTS: BSS rate too low\n"); - r = -1; - goto exit_free_buf; - } - } while (0); - } - - if (slsi_mlme_send_frame_mgmt(sdev, netdev, buf, (IEEE80211_HEADER_SIZE + req_len + ie_len), - FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, - host_tag, 0, sdev->fw_dwell_time, 0) != 0) { - SLSI_ERR(sdev, "CAC-ADDTS: Failed to send ADDTS request\n"); - r = -1; - goto exit_free_buf; - } - entry->dialog_token = req->hdr.dialog_token; - -exit_free_buf: - kfree(buf); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return r; -} - -/* Name: cac_send_delts - * Desc: Build and send the DELTS action frame - * sdev: pointer to the slsi_dev struct - * id: the tspec id that is going the DELTS action frame to send for - * return: 0 (succes), -1 (failure) - */ -static int cac_send_delts(struct slsi_dev *sdev, int id) -{ - struct action_delts_req *req; - struct cac_tspec *entry; - size_t req_len; - u32 priority; - int rc; - struct netdev_vif *ndev_vif; - struct net_device *netdev; - u16 host_tag = slsi_tx_mgmt_host_tag(sdev); - struct ieee80211_hdr *hdr; - u8 *buf = NULL; - u8 *bssid; - u8 r = 0; - struct slsi_peer *stapeer; - - entry = find_tspec_entry(id , 1); - if (entry == NULL) { - SLSI_ERR(sdev, "CAC-DELTS: no TSPEC has been established for tsid=%d\n", id); - return -1; - } - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - netdev = get_netdev_for_station(sdev); - if (netdev == NULL) { - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -1; - } - ndev_vif = netdev_priv(netdev); - if ((ndev_vif == NULL) || (ndev_vif->sta.sta_bss == NULL)) { - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -1; - } - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_ERR(sdev, "CAC-DELTS: Not connected, can't send DELTS\n"); - r = -1; - goto exit; - } - - stapeer = slsi_get_peer_from_qs(sdev, netdev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!stapeer)) { - r = -1; - goto exit; - } - - bssid = ndev_vif->sta.sta_bss->bssid; - buf = kmalloc(24 + sizeof(*req), GFP_KERNEL); - if (buf == NULL) { - SLSI_ERR(sdev, "CAC-DELTS: Failed to allocate DELTS request\n"); - r = -1; - goto exit; - } - hdr = (struct ieee80211_hdr *)buf; - hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, IEEE80211_STYPE_ACTION); - SLSI_ETHER_COPY(hdr->addr1, bssid); - SLSI_ETHER_COPY(hdr->addr2, sdev->hw_addr); - SLSI_ETHER_COPY(hdr->addr3, bssid); - req = (struct action_delts_req *)(buf + 24); - req_len = sizeof(*req); - req->hdr.category = WLAN_CATEGORY_WMM; - req->hdr.action = WMM_ACTION_CODE_DELTS; - req->hdr.dialog_token = 0; - req->hdr.status_code = 0; - memcpy(&req->tspec, &entry->tspec, sizeof(entry->tspec)); - - /* TODO_HARDMAC: If PMF is negotiated over the link, the host shall not - * issue this primitive before pairwise keys have been installed in F/W . - */ - if (slsi_mlme_send_frame_mgmt(sdev, netdev, buf, (IEEE80211_HEADER_SIZE + req_len), FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, 0, 0, 0) != 0) { - SLSI_ERR(sdev, "CAC-DELTS: Failed to send DELTS request\n"); - r = -1; - goto exit_free_buf; - } - rc = cac_query_tspec_field(sdev, entry, "user_priority", &priority); - if (rc != 0) { - SLSI_ERR(sdev, "CAC-DELTS: Error in reading priority from tspec!\n"); - r = -1; - goto exit_free_buf; - } - - if (slsi_mlme_del_traffic_parameters(sdev, netdev, priority) != 0) { - SLSI_ERR(sdev, "CAC-DELTS: Failed to send DELTS request\n"); - r = -1; - goto exit_free_buf; - } - - /* BlockAck Control Req was previously used to enable blockack for VO & VI. This - * signal is removed and expected to be replaced with MIBs - not able to see - * through the haze yet!. Need to take approp. action when the cloud clears. - * Historical Data: - * if the DELTS request is for UP = 4 or 5 then generate a - * MLME-BLOCKACK-CONTROL.request so that no BlockAck is negotiated - * on AC_VI. And leave AC_BE enabled - */ - - entry->accepted = 0; /* DELTS sent successfully */ - sdev->tspec_error_code = 0; - stapeer->tspec_established &= ~BIT(priority); - /* update RIC in add_info_elements for assoc req */ - cac_set_ric_ie(sdev, netdev); - - if (ccx_status == BSS_CCX_ENABLED && previous_msdu_lifetime != MAX_TRANSMIT_MSDU_LIFETIME_NOT_VALID) - if (slsi_send_max_transmit_msdu_lifetime(sdev, netdev, previous_msdu_lifetime) != 0) { - SLSI_ERR(sdev, "CAC-DELTS: slsi_send_max_msdu_lifetime failed"); - goto exit_free_buf; - } -exit_free_buf: - kfree(buf); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return r; -} - -/* Name: cac_create_tspec - * Desc: Create a tspec entry and added it to the tspec list - * sdev: pointer to the slsi_dev struct - * id: the id of the tspec that is included in DELTS action frame - * return: 0 (succes), -1 (failure) - */ -static int cac_create_tspec(struct slsi_dev *sdev, char *args) -{ - struct cac_tspec *entry; - int id; - u8 tid_auto_done = 0; - struct netdev_vif *ndev_vif; - struct net_device *netdev; - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - netdev = get_netdev_for_station(sdev); - if (netdev == NULL) { - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -1; - } - ndev_vif = netdev_priv(netdev); - if (ndev_vif == NULL) { - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -1; - } - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_ERR(sdev, "CAC-ADDTS: Not connected, can't create TSPEC\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -1; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - if (args == NULL) { - /* No input for tid, so we use the auto increment*/ - if (tspec_list_next_id <= 7) { - id = tspec_list_next_id++; - } else { - id = 0; - tspec_list_next_id = 0; - tspec_list_next_id++; - } - tid_auto_done = 1; - } - - if ((!tid_auto_done) && (strtoint(args, &id) < 0)) { - /* Invalid input for tid, so we use the auto increment*/ - if (tspec_list_next_id <= 7) { - id = tspec_list_next_id++; - } else { - id = 0; - tspec_list_next_id = 0; - tspec_list_next_id++; - } - } - - if (id < TSID_MIN || id > TSID_MAX) { - SLSI_ERR(sdev, "CAC: Invalid TSID =%d, must be in range 0-7\n", id); - return -1; - } - - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry == NULL) { - SLSI_ERR(sdev, "CAC: Failed to allocate TSPEC\n"); - return -1; - } - - entry->id = id; - entry->tspec.eid = WLAN_EID_VENDOR_SPECIFIC; - entry->tspec.length = sizeof(entry->tspec) - sizeof(entry->tspec.eid) - sizeof(entry->tspec.length); - CAC_PUT_BE24(entry->tspec.oui, WLAN_OUI_MICROSOFT); - entry->tspec.oui_type = WLAN_OUI_TYPE_MICROSOFT_WMM; - entry->tspec.oui_subtype = WMM_OUI_SUBTYPE_TSPEC_ELEMENT; - entry->tspec.version = WMM_VERSION; - entry->accepted = 0; - entry->psb_specified = 0; - /* Setting the 7th bit of ts info to 1, as its a fixed reserved bit. */ - entry->tspec.ts_info[0] = 0x80; - - entry->next = tspec_list; - tspec_list = entry; - SLSI_DBG1(sdev, SLSI_MLME, "CAC: Created TSPEC entry for id =%d\n", id); - - return entry->id; -} - -/* Name: cac_delete_tspec - * Desc: delete a tspec from the list of the tspecs - * sdev: pointer to the slsi_dev struct - * id: the id of the tspec that will be deleted - * return: 0 (succes), -1 (failure) - */ -static int cac_delete_tspec(struct slsi_dev *sdev, int id) -{ - struct cac_tspec *itr; - struct cac_tspec *prev; - - itr = tspec_list; - prev = NULL; - while (itr != NULL) { - if (itr->id == id) { - if (prev) - prev->next = itr->next; - else - tspec_list = itr->next; - - if (itr->accepted) - cac_send_delts(sdev, itr->id); - - SLSI_DBG3(sdev, SLSI_MLME, "CAC: TSPEC entry deleted for id =%d\n", id); - kfree(itr); - - return 0; - } - prev = itr; - itr = itr->next; - } - SLSI_ERR(sdev, "CAC: Couldn't find TSPEC with id %d for deletion", id); - - return -1; -} - -/* Name: cac_delete_tspec_by_state - * Desc: delete a tspec from the list of the tspecs based on id and state - * sdev: pointer to the slsi_dev struct - * id: the id of the tspec that will be deleted - * accepted: 0 - not yet accepted by AP, 1- accepted by AP - * return: 0 (succes), -1 (failure) - */ -static int cac_delete_tspec_by_state(struct slsi_dev *sdev, int id, int accepted) -{ - struct cac_tspec *itr; - struct cac_tspec *prev; - - itr = tspec_list; - prev = NULL; - while (itr != NULL) { - if ((itr->id == id) && (itr->accepted == accepted)) { - if (prev) - prev->next = itr->next; - else - tspec_list = itr->next; - - SLSI_DBG3(sdev, SLSI_MLME, "CAC: Deleting TSPEC 0x%p with ID %d (accepted =%d)\n", itr, id, accepted); - kfree(itr); - return 0; - } - prev = itr; - itr = itr->next; - } - SLSI_ERR(sdev, "CAC: Couldn't find TSPEC with ID %d (accepted =%d)\n", id, accepted); - - return -1; -} - -/* Name: cac_config_tspec - * Desc: Set a field's value of a tspec - * sdev: pointer to the slsi_dev struct - * id: the id of the tspec that will be configured - * field: the field name that will be changed - * value: the value of the field - * return: 0 (succes), -1 (failure) - */ -static int cac_config_tspec(struct slsi_dev *sdev, int id, const char *field, u32 value) -{ - struct cac_tspec *entry; - int i; - u32 max = 0xFFFFFFFF; - u32 tsinfo; - u8 mask; - u8 *pos; - - if (field == NULL) - return -1; - - entry = find_tspec_entry(id, 0); - if (entry == NULL) { - SLSI_ERR(sdev, "CAC: Invalid TSPEC ID\n"); - return -1; - } - - for (i = 0; i < NUM_TSPEC_FIELDS; i++) - if (strcasecmp(field, tspec_fields[i].name) == 0) - break; - if (i >= NUM_TSPEC_FIELDS) { - SLSI_ERR(sdev, "CAC: Invalid TSPEC config field\n"); - return -1; - } - if (tspec_fields[i].read_only) { - SLSI_ERR(sdev, "CAC: TSPEC field is read-only\n"); - return -1; - } - if (tspec_fields[i].is_tsinfo_field) { - mask = tspec_fields[i].size; - if (strcasecmp(field, "psb") == 0) { - if (value <= mask) - entry->psb_specified = 1; - else - return 0; - } - if (value > mask) { - SLSI_ERR(sdev, "CAC: TSPEC config value exceeded maximum for %s\n", tspec_fields[i].name); - return -1; - } - - tsinfo = CAC_GET_LE24(&entry->tspec.ts_info[0]); - tsinfo &= ~(u32)(mask << tspec_fields[i].offset); - tsinfo |= (u32)((value & mask) << tspec_fields[i].offset); - CAC_PUT_LE24(entry->tspec.ts_info, tsinfo); - } else { - if (tspec_fields[i].size < 4) - max = ((1 << (tspec_fields[i].size * 8)) - 1); - - if (value > max) { - SLSI_ERR(sdev, "CAC: TSPEC config value exceeded maximumfor %s\n", tspec_fields[i].name); - return -1; - } - - pos = (u8 *)(&entry->tspec) + tspec_fields[i].offset; - if (tspec_fields[i].size == 1) - *pos = (value & 0xFF); - else if (tspec_fields[i].size == 2) - CAC_PUT_LE16(pos, value); - else - CAC_PUT_LE32(pos, value); - } - - return 0; -} - -/* Name: cac_ctrl_create_tspec - * Desc: public function to create tspec - * sdev: pointer to the slsi_dev struct - * return: tspec id - */ -int cac_ctrl_create_tspec(struct slsi_dev *sdev, char *args) -{ - int id; - - id = cac_create_tspec(sdev, args); - if (id < 0) - return -1; - - return id; -} - -/* Name: cac_ctrl_delete_tspec - * Desc: public function to delete tspec - * sdev: pointer to the slsi_dev struct - * args:pointer to a buffer that contains the agrs for deleting tspec from the list - * return: 0 (succes), -1 (failure) - */ -int cac_ctrl_delete_tspec(struct slsi_dev *sdev, char *args) -{ - int id; - - if (strtoint(args, &id) < 0) { - SLSI_ERR(sdev, "CAC-DELETE-TSPEC: Invalid TSPEC ID\n"); - return -1; - } - - if (cac_delete_tspec(sdev, id) < 0) - return -1; - - return 0; -} - -/* Name: cac_ctrl_config_tspec - * Desc: public function to configure a tspec - * sdev: pointer to the slsi_dev struct - * args: pointer to a buffer that contains the agrs for tspec configuration - * return: 0 (succes), -1 (failure) - */ -int cac_ctrl_config_tspec(struct slsi_dev *sdev, char *args) -{ - char *id; - char *field; - char *value; - int tspec_id; - u32 val; - - id = args; - field = strchr(id, ' '); - if (field == NULL) { - SLSI_ERR(sdev, "CAC: field string is NULL\n"); - return -1; - } - *field++ = '\0'; - value = strchr(field, ' '); - if (value == NULL) { - SLSI_ERR(sdev, "CAC: field value is NULL\n"); - return -1; - } - *value++ = '\0'; - - if (strtoint(id, &tspec_id) < 0) { - SLSI_ERR(sdev, "CAC: Conversion error for tspecid\n"); - return -1; - } - - if (strtoint(value, &val) < 0) { - SLSI_ERR(sdev, "CAC: Conversion error for tspecid value\n"); - return -1; - } - - if (cac_config_tspec(sdev, tspec_id, field, val) < 0) - return -1; - - return 0; -} - -/* Name: cac_ctrl_send_addts - * Desc: public function to send ADDTS action frame - * sdev: pointer to the slsi_dev struct - * args: buffer that contains the agrs for ADDTS request - * return: 0 (succes), -1 (failure) - */ -int cac_ctrl_send_addts(struct slsi_dev *sdev, char *args) -{ - char *id_str; - char *ebw_str; - int id; - int ebw = 0; - - if (args == NULL) - return -1; - - id_str = args; - ebw_str = strchr(id_str, ' '); - if (ebw_str != NULL) { - *ebw_str++ = '\0'; - if (!strncmp(ebw_str, "ebw", 3)) - ebw = 1; - } - if (strtoint(id_str, &id) < 0) { - SLSI_ERR(sdev, "CAC: Conversion error for tspecid value\n"); - return -1; - } - if (cac_send_addts(sdev, id, ebw) < 0) - return -1; - - return 0; -} - -/* Name: cac_ctrl_send_delts - * Desc: public function to send DELTS action frame - * sdev: pointer to the slsi_dev struct - * args: buffer that contains the agrs for DELTS request - * return: 0 (succes), -1 (failure) - */ -int cac_ctrl_send_delts(struct slsi_dev *sdev, char *args) -{ - int id; - - if (args == NULL) - return -1; - - if (strtoint(args, &id) < 0) { - SLSI_ERR(sdev, "CAC: Invalid TSPEC ID\n"); - return -1; - } - if (cac_send_delts(sdev, id) < 0) - return -1; - - return 0; -} - -/* Name: cac_process_delts_req - * Desc: process a DELTS request - * sdev: pointer to the slsi_dev struct - * req: buffer of the DELTS request - * return: 0 (succes), -1 (failure) - */ -static void cac_process_delts_req(struct slsi_dev *sdev, struct net_device *netdev, struct action_delts_req *req) -{ - struct netdev_vif *ndev_vif = netdev_priv(netdev); - struct cac_tspec *itr; - u32 priority; - int rc; - struct slsi_peer *stapeer; - u8 tid; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED) || (ndev_vif->sta.sta_bss == NULL)) { - SLSI_ERR(sdev, "CAC: Not connected, Unexpected DELTS request\n"); - return; - } - - stapeer = slsi_get_peer_from_qs(sdev, netdev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!stapeer)) - return; - - tid = (CAC_GET_LE24(req->tspec.ts_info) >> 1) & 0xF; - SLSI_DBG1(sdev, SLSI_MLME, "CAC: TID in delts request =%d\n", tid); - - itr = find_tspec_entry(tid, 1); - if (itr == NULL) { - SLSI_ERR(sdev, "CAC: No matching TSPEC found\n"); - return; - } - - rc = cac_query_tspec_field(sdev, itr, "user_priority", &priority); - if (rc != 0) { - SLSI_ERR(sdev, "CAC: Missing priority from TSPEC!\n"); - return; - } - - if (slsi_mlme_del_traffic_parameters(sdev, netdev, priority) != 0) { - SLSI_ERR(sdev, "CAC: Failed to send DEL-TRAFFIC_PARAMETERS request\n"); - return; - } - - /* BlockAck Control Req was previously used to enable blockack for VO & VI. This - * signal is removed and expected to be replaced with MIBs - not able to see - * through the haze yet!. Need to take approp. action when the cloud clears. - * Historical Data: - * if the DELTS request is for UP = 4 or 5 then generate a - * MLME-BLOCKACK-CONTROL.request so that no BlockAck is negotiated - * on AC_VI. And leave AC_BE enabled - */ - - itr->accepted = 0; /* del traffic parameters sent successfully */ - stapeer->tspec_established &= ~BIT(priority); - SLSI_DBG1(sdev, SLSI_MLME, "tspec_established =%x\n", stapeer->tspec_established); - /* update RIC in add_info_elements for assoc req */ - cac_set_ric_ie(sdev, netdev); - - if (ccx_status == BSS_CCX_ENABLED && previous_msdu_lifetime != MAX_TRANSMIT_MSDU_LIFETIME_NOT_VALID) - if (slsi_send_max_transmit_msdu_lifetime(sdev, netdev, previous_msdu_lifetime) != 0) { - SLSI_ERR(sdev, "CAC: slsi_send_max_msdu_lifetime failed"); - return; - } -} - -/* Name: cac_find_edca_ie - * Desc: Finds the edca IE in the ADDTS response action frame - * sdev: pointer to the slsi_dev struct - * ie: buffer of the edca IE - * tsid: the tsid that is included in the edca IE - * lifetime: the lifetime value that is included in the edca IE - * return: 0 (succes), -1 (failure) - */ -static int cac_find_edca_ie(const u8 *ie, size_t ie_len, u8 *tsid, u16 *lifetime) -{ - const u8 *pos = ie; - - if ((ie == NULL) || (ie_len < 9) || - (tsid == NULL) || (lifetime == NULL)) - return -1; - - pos = cfg80211_find_vendor_ie(WLAN_OUI_CISCO, WLAN_OUI_TYPE_CISCO_EDCA, ie, ie_len); - if (pos && (pos + 9 <= ie + ie_len)) { - *tsid = pos[6]; - *lifetime = CAC_GET_LE16(&pos[7]); - return 0; - } - - return -1; -} - -/* Name: cac_process_addts_rsp - * Desc: parsing of the addts response - * sdev: pointer to the slsi_dev struct - * rsp: the buffer of the ADDTS response received - * ie_len: the length of the buffer - * return: 0 (succes), -1 (failure) - */ -static void cac_process_addts_rsp(struct slsi_dev *sdev, struct net_device *netdev, struct action_addts_rsp *rsp, const u8 *ie, size_t ie_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(netdev); - struct cac_tspec *itr, *entry; - struct wmm_tspec_element *tspec; - u32 priority, prev_priority; - int rc; - u8 tsid; - u16 msdu_lifetime; - struct slsi_peer *peer; - u16 medium_time; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_DBG1(sdev, SLSI_MLME, "\n"); - - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED) || (ndev_vif->sta.sta_bss == NULL)) { - SLSI_ERR(sdev, "CAC: Not connected, INVALID state for ADDTS response\n"); - return; - } - - peer = slsi_get_peer_from_qs(sdev, netdev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!peer)) - return; - - itr = tspec_list; - while (itr != NULL) { - if (itr->dialog_token == rsp->hdr.dialog_token) { - itr->dialog_token = 0; /*reset the dialog token to avoid any incorrect matches if AP send incorrect value*/ - break; - } - itr = itr->next; - } - if (itr == NULL) { - SLSI_ERR(sdev, "CAC: No matching TSPEC found for ADDTS response\n"); - return; - } - - if (rsp->hdr.status_code != ADDTS_STATUS_ACCEPTED) { - SLSI_ERR(sdev, "CAC: TSPEC rejected (status=0x%02X)", rsp->hdr.status_code); - cac_delete_tspec_by_state(sdev, itr->id , 0); - return; - } - - if ((ccx_status == BSS_CCX_ENABLED) && cac_find_edca_ie(ie, ie_len, &tsid, &msdu_lifetime) != 0) - msdu_lifetime = MSDU_LIFETIME_DEFAULT; - - tspec = (struct wmm_tspec_element *)(rsp + 1); - medium_time = tspec->medium_time; - - rc = cac_query_tspec_field(sdev, itr, "user_priority", &priority); - SLSI_DBG1(sdev, SLSI_MLME, "CAC: Priority for current tspec id %d=%d\n", itr->id, priority); - - if (peer->tspec_established == 0) - goto set_params; - - SLSI_DBG1(sdev, SLSI_MLME, "TSPEC already established\n"); - - /* TSPEC is already established . Check if it is for same UP / UP mapping to same AC - * If same UP (or UP mapping to same AC) : set params with modified values - * If not, set traffic params for this priority (new AC) - */ - switch (priority) { - /*AC_BK*/ - case FAPI_PRIORITY_QOS_UP1: - case FAPI_PRIORITY_QOS_UP2: - if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP1)) - prev_priority = FAPI_PRIORITY_QOS_UP1; - else if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP2)) - prev_priority = FAPI_PRIORITY_QOS_UP2; - else - goto set_params; - break; - - /*AC_BE*/ - case FAPI_PRIORITY_QOS_UP0: - case FAPI_PRIORITY_QOS_UP3: - if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP0)) - prev_priority = FAPI_PRIORITY_QOS_UP0; - else if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP3)) - prev_priority = FAPI_PRIORITY_QOS_UP3; - else - goto set_params; - break; - - /*AC_VI*/ - case FAPI_PRIORITY_QOS_UP4: - case FAPI_PRIORITY_QOS_UP5: - if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP4)) - prev_priority = FAPI_PRIORITY_QOS_UP4; - else if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP5)) - prev_priority = FAPI_PRIORITY_QOS_UP5; - else - goto set_params; - break; - - /*AC_VO*/ - case FAPI_PRIORITY_QOS_UP6: - case FAPI_PRIORITY_QOS_UP7: - if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP6)) - prev_priority = FAPI_PRIORITY_QOS_UP6; - else if (peer->tspec_established & BIT(FAPI_PRIORITY_QOS_UP7)) - prev_priority = FAPI_PRIORITY_QOS_UP7; - else - goto set_params; - break; - /* invalid*/ - default: - SLSI_ERR(sdev, "CAC: Invalid UP in the request\n"); - return; - } - - /* Look for TSPEC entry for initial request */ - entry = find_tspec_entry(itr->id, 1); - if (entry) { /*same TID*/ - cac_query_tspec_field(sdev, entry, "user_priority", &prev_priority); - SLSI_DBG1(sdev, SLSI_MLME, "CAC: Modify TSPEC (prev_priority =%d)\n", prev_priority); - /* On receiving the new medium time (second ADDTS Response) , driver shall issue - * mlme-set-traffic-parameters.request with the received medium time. - * Use UP from old entry so FW can replace the medium time - * Delete the old entry in host, and replace UP in new entry. - */ - cac_delete_tspec_by_state(sdev, entry->id, 1); - if (priority != prev_priority) { - itr->tspec.ts_info[1] &= ~(7 << 3) ; /*clear the value*/ - itr->tspec.ts_info[1] |= prev_priority << 3 ; /*set the value*/ - priority = prev_priority; - } - - } else { - /* Two distinct TSes are being admitted, so the driver needs to add both allocated medium time - * The UP must be set to the same value of the first mlme-set-traffic-parameters.request so that - * the FW replaces the current medium time with the new medium time. - */ - SLSI_DBG1(sdev, SLSI_MLME, "CAC: Modify TSPEC for different TID\n"); - entry = tspec_list; - while (entry != NULL) { - if ((entry->accepted) && ((entry->tspec.ts_info[1] >> 3 & 0x07) == prev_priority)) { /*initial TS entry for same priority*/ - medium_time += entry->tspec.medium_time; - priority = prev_priority; - break; - } - entry = entry->next; - } - if (entry == NULL) { - SLSI_ERR(sdev, "CAC: Failed to find entry for prev established TSPEC!!\n"); - return; - } - } - -set_params: - SLSI_DBG1(sdev, SLSI_MLME, "sending traffic params tid [%d]", itr->id); - if (slsi_mlme_set_traffic_parameters(sdev, netdev, priority, medium_time, tspec->minimum_data_rate, ndev_vif->sta.sta_bss->bssid) != 0) { - SLSI_ERR(sdev, "CAC: Failed to send SET_TRAFFIC_PARAMETERS request\n"); - return; - } - - /*update the TSPEC with medium_time allocated by AP*/ - itr->tspec.medium_time = medium_time; - - /* BlockAck Control Req was previously used to enable blockack for VO & VI. This - * signal is removed and expected to be replaced with MIBs - not able to see - * through the haze yet!. Need to take approp. action when the cloud clears. - * Historical Data: - * Currently the firmware autonomously negotiates BlockAck agreement for AC_BE. - * It is required for WMM-AC certification to use BlockAck for AC_VI. - * So if a TSPEC for AC_VI (UP = 5 0r 4) is successfully negotiated, the host - * generates an MLME-BLOCKACK-CONTROL.request, identifying that a BlockAck for the - * corresponding Priority (direction set to Any) should be enabled, i.e. the F/W - * will accept a downlink requested BlockAck Request, and will try to set-up an - * uplink BlockAck Request for that priority (TID). - * Bits for AC_BE should always be set - * For WMM-AC certification, if the EDCA parameters for both VO and VI are same - * during association and both are ACM = 1, then don't use BlockAck for AC_VI. - */ - - /* Add store in MIB the msdu_lifetime value in case of ccx enabled bss */ - if (ccx_status == BSS_CCX_ENABLED) { - if ((slsi_read_max_transmit_msdu_lifetime(sdev, netdev, &previous_msdu_lifetime)) != 0) { - previous_msdu_lifetime = MAX_TRANSMIT_MSDU_LIFETIME_NOT_VALID; - SLSI_ERR(sdev, "CAC: slsi_read_max_msdu_lifetime failed"); - return; - } - - if (slsi_send_max_transmit_msdu_lifetime(sdev, netdev, msdu_lifetime) != 0) { - SLSI_ERR(sdev, "CAC: slsi_send_max_msdu_lifetime failed"); - return; - } - } - - itr->accepted = 1; /* add_tspec accepted by AP*/ - sdev->tspec_error_code = 0; /* add_tspec response received */ - peer->tspec_established |= BIT(priority); - /* update RIC in add_info_elements for assoc req */ - cac_set_ric_ie(sdev, netdev); -} - -/* Name: cac_rx_wmm_action - * Desc: Get the action frame received and call the corresponding process routine - * sdev: pointer to the slsi_dev struct - * data: buffer to the action frame received - * len: the length in bytes of the action frame - */ -void cac_rx_wmm_action(struct slsi_dev *sdev, struct net_device *netdev, struct ieee80211_mgmt *data, size_t len) -{ - struct ieee80211_mgmt *mgmt = data; - struct action_addts_rsp *addts; - - if ((sdev == NULL) || (data == NULL) || (netdev == NULL) || (len == 0)) - return; - - if (mgmt->u.action.u.wme_action.action_code == WMM_ACTION_CODE_ADDTS_RESP) { - addts = (struct action_addts_rsp *)&mgmt->u.action; - cac_process_addts_rsp(sdev, netdev, addts, mgmt->u.action.u.wme_action.variable, len - sizeof(*addts) + 1); - } else if (mgmt->u.action.u.wme_action.action_code == WMM_ACTION_CODE_DELTS) { - cac_process_delts_req(sdev, netdev, (struct action_delts_req *)&mgmt->u.action); - } -} - -/* Name: cac_get_active_tspecs - * Desc: - * tspecs: the list of active tspecs - * return: 0 (succes), -1 (failure) - */ -int cac_get_active_tspecs(struct cac_activated_tspec **tspecs) -{ - struct cac_tspec *itr = tspec_list; - int count = 0; - int i = 0; - - if (tspecs == NULL) - return -1; - - while (itr != NULL) { - if (itr->accepted) - count++; - itr = itr->next; - } - *tspecs = kmalloc_array((size_t)count, sizeof(struct cac_activated_tspec), GFP_KERNEL); - itr = tspec_list; - while (itr != NULL) { - if (itr->accepted) { - tspecs[i]->ebw = itr->ebw; - memcpy(&tspecs[i]->tspec, &itr->tspec, sizeof(itr->tspec)); - i++; - } - itr = itr->next; - } - - return count; -} - -/********************************************************* - * call cac_delete_tspec_list to delete all tspecs - * when the device is disconnecting - */ -/* Name: cac_delete_tspec_list - * Desc: - * sdev: pointer to the slsi_dev struct - * return: None - */ -void cac_delete_tspec_list(struct slsi_dev *sdev) -{ - struct cac_tspec *itr = tspec_list; - struct cac_tspec *temp = NULL; - - SLSI_UNUSED_PARAMETER(sdev); - - while (itr != NULL) { - itr->accepted = 0; - itr->dialog_token = 0; - temp = itr; - itr = itr->next; - kfree(temp); - } - tspec_list = NULL; -} - -void cac_deactivate_tspecs(struct slsi_dev *sdev) -{ - struct cac_tspec *itr = tspec_list; - - SLSI_UNUSED_PARAMETER(sdev); - - while (itr) { - itr->accepted = 0; - itr->dialog_token = 0; - itr = itr->next; - } -} - -static void cac_set_ric_ie(struct slsi_dev *sdev, struct net_device *netdev) -{ - struct cac_tspec *itr = tspec_list; - int tspec_count = 0; - int buf_len = 0; - u8 *buff, *add_info_ies; - struct wmm_tspec_element *tspec_ie; - int i = 0; - struct netdev_vif *ndev_vif = netdev_priv(netdev); - - while (itr) { - if (itr->accepted) - tspec_count++; - itr = itr->next; - } - - if (tspec_count == 0) { - slsi_mlme_add_info_elements(sdev, netdev, FAPI_PURPOSE_ASSOCIATION_REQUEST, - ndev_vif->sta.assoc_req_add_info_elem, - ndev_vif->sta.assoc_req_add_info_elem_len); - return; - } - - /* RDE (6 bytes), WMM TSPEC * tspec_count bytes*/ - buf_len = 6 + (sizeof(struct wmm_tspec_element) * tspec_count); - buf_len += ndev_vif->sta.assoc_req_add_info_elem_len; - add_info_ies = kmalloc(buf_len, GFP_KERNEL); - if (!add_info_ies) { - SLSI_ERR(sdev, "malloc fail. size:%d\n", buf_len); - return; - } - memcpy(add_info_ies, ndev_vif->sta.assoc_req_add_info_elem, ndev_vif->sta.assoc_req_add_info_elem_len); - - buff = add_info_ies + ndev_vif->sta.assoc_req_add_info_elem_len; - buff[0] = WLAN_EID_RIC_DATA; - buff[1] = 4; - buff[2] = 0; /* random identifier */ - /* buff[3]: resource desc count update after filling TSPEC */ - buff[4] = 0; /* buff[4]-buff[5] status code. set to success */ - buff[5] = 0; - - itr = tspec_list; - i = 0; - while (itr) { - if (itr->accepted) { - tspec_ie = (struct wmm_tspec_element *)&buff[6 + i * sizeof(struct wmm_tspec_element)]; - memcpy(tspec_ie, &itr->tspec, sizeof(struct wmm_tspec_element)); - ((struct wmm_tspec_element *)tspec_ie)->medium_time = 0; - i++; - } - itr = itr->next; - } - buff[3] = i; - slsi_mlme_add_info_elements(sdev, netdev, FAPI_PURPOSE_ASSOCIATION_REQUEST, add_info_ies, buf_len); - kfree(add_info_ies); -} - -static int cac_get_rde_tspec_ie(struct slsi_dev *sdev, u8 *assoc_rsp_ie, int assoc_rsp_ie_len, const u8 **tspec_ie_arr) -{ - const u8 *ie; - u16 status; - int tspec_count = 0, i = 0; - - ie = assoc_rsp_ie; - - /* Find total number of RDE TSPEC */ - while (ie && (assoc_rsp_ie_len > ie - assoc_rsp_ie)) { - ie = cfg80211_find_ie(WLAN_EID_RIC_DATA, ie, assoc_rsp_ie_len - (ie - assoc_rsp_ie)); - if (!ie) - break; - status = CAC_GET_LE16(&ie[4]); - if (status != 0) - continue; - - tspec_count += ie[3]; /* TSPEC descriptor count */ - ie = ie + ie[1]; - } - - /* limit WMM TSPEC count to TSID_MAX */ - if (tspec_count > TSID_MAX) { - SLSI_DBG1(sdev, SLSI_MLME, "received %d TSPEC but can accommodate only %d\n", tspec_count, TSID_MAX); - tspec_count = TSID_MAX; - } - - /* Get all WMM TSPEC IE pointers */ - ie = cfg80211_find_ie(WLAN_EID_RIC_DATA, assoc_rsp_ie, assoc_rsp_ie_len); - while (i < tspec_count && ie) { - ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WMM, ie, - assoc_rsp_ie_len - (ie - assoc_rsp_ie)); - if (!ie) - break; - /* re-assoc-res can contain wmm parameter IE and wmm TSPEC IE. - * we want wmm TSPEC Element) - */ - if (ie[1] > 6 && ie[6] == WMM_OUI_SUBTYPE_TSPEC_ELEMENT) { - tspec_ie_arr[i] = ie; - i++; - } - ie += ie[1]; - } - - return i; -} - -void cac_update_roam_traffic_params(struct slsi_dev *sdev, struct net_device *dev) -{ - const u8 *tspec_ie_arr[TSID_MAX]; - int assoc_rsp_tspec_count, i; - u32 priority; - struct cac_tspec *itr; - struct wmm_tspec_element *assoc_rsp_tspec; - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_DBG3(sdev, SLSI_MLME, "\n"); - - /* Roamed to new AP. TSPEC admitted to previous AP are no more valid. - * Set all TSPEC to not admitted - */ - cac_deactivate_tspecs(sdev); - - if (!peer) { - SLSI_ERR(sdev, "AP peer entry not found\n"); - return; - } - - /* Find all the admitted TSPECs in assoc resp. */ - assoc_rsp_tspec_count = cac_get_rde_tspec_ie(sdev, peer->assoc_resp_ie->data, - peer->assoc_resp_ie->len, tspec_ie_arr); - - SLSI_DBG3(sdev, SLSI_MLME, "assoc_rsp_tspec_count:%d\n", assoc_rsp_tspec_count); - - if (!assoc_rsp_tspec_count) - return; - - /* update the admitted TSPECs from assoc resp and set traffic params in FW.*/ - for (i = 0; i < assoc_rsp_tspec_count; i++) { - assoc_rsp_tspec = (struct wmm_tspec_element *)tspec_ie_arr[i]; - SLSI_DBG3(sdev, SLSI_MLME, "rsp_tspec:[%d] ts: [%x|%x|%x] medium time[%x]\n", i, - assoc_rsp_tspec->ts_info[0], assoc_rsp_tspec->ts_info[1], assoc_rsp_tspec->ts_info[2], - assoc_rsp_tspec->medium_time); - - itr = find_tspec_entry((assoc_rsp_tspec->ts_info[0] & 0x1E) >> 1, 0); - if (!itr) { - SLSI_DBG3(sdev, SLSI_MLME, "tspec entry not found\n"); - continue; - } - - itr->tspec.medium_time = assoc_rsp_tspec->medium_time; - itr->tspec.minimum_data_rate = assoc_rsp_tspec->minimum_data_rate; - itr->accepted = 1; - cac_query_tspec_field(sdev, itr, "user_priority", &priority); - peer->tspec_established |= BIT(priority); - SLSI_DBG3(sdev, SLSI_MLME, "tspec admitted id[%d]\n", itr->id); - slsi_mlme_set_traffic_parameters(sdev, dev, priority, assoc_rsp_tspec->medium_time, - assoc_rsp_tspec->minimum_data_rate, ndev_vif->sta.sta_bss->bssid); - } -} - diff --git a/drivers/net/wireless/scsc/cac.h b/drivers/net/wireless/scsc/cac.h deleted file mode 100755 index a8851eb4b455..000000000000 --- a/drivers/net/wireless/scsc/cac.h +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef CAC_H -#define CAC_H - -#include -#include "dev.h" -#include "debug.h" -#include "mlme.h" -#include "mgt.h" - -/* management */ -#define WLAN_OUI_CISCO 0x004096 /* Cisco systems OUI */ -#define WLAN_OUI_TYPE_CISCO_EDCA 0x09 - -#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WMM_VERSION 1 -#define WMM_ACTION_CODE_ADDTS_REQ 0 -#define WMM_ACTION_CODE_ADDTS_RESP 1 -#define WMM_ACTION_CODE_DELTS 2 -#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0 -#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1 -/* 2 - Reserved */ -#define WMM_ADDTS_STATUS_REFUSED 3 -/* 4-255 - Reserved */ - -/* WMM TSPEC Direction Field Values */ -#define WMM_TSPEC_DIRECTION_UPLINK 0 -#define WMM_TSPEC_DIRECTION_DOWNLINK 1 -/* 2 - Reserved */ -#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 - -/* WMM TSPEC PSB Field Values */ -#define WMM_TSPEC_PSB_UNSPECIFIED 2 - -#define ADDTS_STATUS_ACCEPTED 0x00 -#define ADDTS_STATUS_INVALID_PARAM 0x01 -#define ADDTS_STATUS_REFUSED 0x03 -#define ADDTS_STATUS_DELAY 0x2F -#define ADDTS_STATUS_UNSPECIFIED 0xC8 -#define ADDTS_STATUS_POLICY_CONFIG 0xC9 -#define ADDTS_STATUS_ASSOC_DENIED 0xCA -#define ADDTS_STATUS_INVALID_PARAM2 0xCB - -#define TSINFO_MASK 0x00FFFFFF - -#define CCX_MAX_NUM_RATES 8 - -#define TSID_MIN 0 -#define TSID_MAX 7 - -#define TSRS_RATE_PER_UNIT 500000 -#define IEEE80211_HEADER_SIZE 24 - -#define MAX_TRANSMIT_MSDU_LIFETIME_NOT_VALID -1 -#define BSS_CCX_DISABLED 0 -#define BSS_CCX_ENABLED 1 - -/* Macros for handling unaligned memory accesses */ -#define CAC_GET_LE16(a) ((u16)(((a)[1] << 8) | (a)[0])) -#define CAC_PUT_LE16(a, val) \ - do { \ - (a)[1] = ((u16)(val)) >> 8; \ - (a)[0] = ((u16)(val)) & 0xff; \ - } while (0) -#define CAC_PUT_BE24(a, val) \ - do { \ - (a)[0] = (u8)((((u32)(val)) >> 16) & 0xff); \ - (a)[1] = (u8)((((u32)(val)) >> 8) & 0xff); \ - (a)[2] = (u8)(((u32)(val)) & 0xff); \ - } while (0) -#define CAC_GET_LE24(a) ((((u32)(a)[2]) << 16) | (((u32)(a)[1]) << 8) | ((u32)(a)[0])) -#define CAC_PUT_LE24(a, val) \ - do { \ - (a)[2] = (u8)((((u32)(val)) >> 16) & 0xff); \ - (a)[1] = (u8)((((u32)(val)) >> 8) & 0xff); \ - (a)[0] = (u8)(((u32)(val)) & 0xff); \ - } while (0) -#define CAC_GET_LE32(a) ((((u32)(a)[3]) << 24) | (((u32)(a)[2]) << 16) | \ - (((u32)(a)[1]) << 8) | ((u32)(a)[0])) -#define CAC_PUT_LE32(a, val) \ - do { \ - (a)[3] = (u8)((((u32)(val)) >> 24) & 0xff); \ - (a)[2] = (u8)((((u32)(val)) >> 16) & 0xff); \ - (a)[1] = (u8)((((u32)(val)) >> 8) & 0xff); \ - (a)[0] = (u8)(((u32)(val)) & 0xff); \ - } while (0) - -#define IEEE80211_FC(type, stype) (u16)(type | stype) - -/* WMM TSPEC Element */ -struct wmm_tspec_element { - char eid; /* 221 = 0xdd */ - u8 length; /* 6 + 55 = 61 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 2 */ - u8 version; /* 1 */ - /* WMM TSPEC body (55 octets): */ - u8 ts_info[3]; - u16 nominal_msdu_size; - u16 maximum_msdu_size; - u32 minimum_service_interval; - u32 maximum_service_interval; - u32 inactivity_interval; - u32 suspension_interval; - u32 service_start_time; - u32 minimum_data_rate; - u32 mean_data_rate; - u32 peak_data_rate; - u32 maximum_burst_size; - u32 delay_bound; - u32 minimum_phy_rate; - u16 surplus_bandwidth_allowance; - u16 medium_time; -} __packed; - -#define MSDU_LIFETIME_DEFAULT 512 - -struct cac_activated_tspec { - struct wmm_tspec_element tspec; - int ebw; -}; - -struct tspec_field { - const char *name; - int read_only; - int is_tsinfo_field; - u8 size; - u32 offset; -}; - -struct cac_tspec { - struct cac_tspec *next; - int id; - struct wmm_tspec_element tspec; - u8 psb_specified; - int ebw; - int accepted; - u8 dialog_token; -}; - -#define OFFSETOF(m) ((size_t)&((struct wmm_tspec_element *)0)->m) - -struct wmm_action_hdr { - u8 category; - u8 action; - u8 dialog_token; - u8 status_code; -} __packed; - -struct action_addts_req { - struct wmm_action_hdr hdr; - struct wmm_tspec_element tspec; -} __packed; - -struct action_addts_rsp { - struct wmm_action_hdr hdr; -} __packed; - -struct action_delts_req { - struct wmm_action_hdr hdr; - struct wmm_tspec_element tspec; -} __packed; -/* prototypes for public functions */ -int cac_ctrl_create_tspec(struct slsi_dev *sdev, char *args); -int cac_ctrl_config_tspec(struct slsi_dev *sdev, char *args); -int cac_ctrl_send_addts(struct slsi_dev *sdev, char *args); -int cac_ctrl_send_delts(struct slsi_dev *sdev, char *args); -int cac_update_local_tspec(struct slsi_dev *sdev, u16 msdu_lifetime, struct wmm_tspec_element *tspec); -int cac_get_active_tspecs(struct cac_activated_tspec **tspecs); -void cac_delete_tspec_list(struct slsi_dev *sdev); -int cac_ctrl_delete_tspec(struct slsi_dev *sdev, char *args); -void cac_rx_wmm_action(struct slsi_dev *sdev, struct net_device *netdev, struct ieee80211_mgmt *data, size_t len); -void cac_update_roam_traffic_params(struct slsi_dev *sdev, struct net_device *dev); -#endif /* CAC_H */ diff --git a/drivers/net/wireless/scsc/cfg80211_ops.c b/drivers/net/wireless/scsc/cfg80211_ops.c deleted file mode 100755 index f67eaf52d6dd..000000000000 --- a/drivers/net/wireless/scsc/cfg80211_ops.c +++ /dev/null @@ -1,3567 +0,0 @@ -/*************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include "dev.h" -#include "cfg80211_ops.h" -#include "debug.h" -#include "mgt.h" -#include "mlme.h" -#include "netif.h" -#include "unifiio.h" -#include "mib.h" - -#ifdef CONFIG_ANDROID -#include "scsc_wifilogger_rings.h" -#endif -#include "nl80211_vendor.h" - -#define SLSI_MAX_CHAN_2G_BAND 14 - -static uint keep_alive_period = SLSI_P2PGO_KEEP_ALIVE_PERIOD_SEC; -module_param(keep_alive_period, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(keep_alive_period, "default is 10 seconds"); - -static bool slsi_is_mhs_active(struct slsi_dev *sdev) -{ - struct net_device *mhs_dev = sdev->netdev_ap; - struct netdev_vif *ndev_vif; - bool ret; - - if (mhs_dev) { - ndev_vif = netdev_priv(mhs_dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - ret = ndev_vif->is_available; - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return ret; - } - - return 0; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) -struct wireless_dev *slsi_add_virtual_intf(struct wiphy *wiphy, - const char *name, - unsigned char name_assign_type, - enum nl80211_iftype type, - struct vif_params *params) -{ -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) -struct wireless_dev *slsi_add_virtual_intf(struct wiphy *wiphy, - const char *name, - unsigned char name_assign_type, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params) -{ -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -struct wireless_dev *slsi_add_virtual_intf(struct wiphy *wiphy, - const char *name, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params) -{ -#else -struct net_device *slsi_add_ virtual_intf(struct wiphy *wiphy, - char *name, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params) -{ -#endif - - struct net_device *dev = NULL; - struct netdev_vif *ndev_vif = NULL; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 0)) - SLSI_UNUSED_PARAMETER(flags); -#endif - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Intf name:%s, type:%d, macaddr:%pM\n", name, type, params->macaddr); - if (slsi_is_mhs_active(sdev)) { - SLSI_ERR(sdev, "MHS is active. cannot add new interface\n"); - return ERR_PTR(-EOPNOTSUPP); - } - dev = slsi_dynamic_interface_create(wiphy, name, type, params); - if (!dev) - goto exit_with_error; - ndev_vif = netdev_priv(dev); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - return &ndev_vif->wdev; -#else - return dev; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) */ - -exit_with_error: - return ERR_PTR(-ENODEV); -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) -{ - struct net_device *dev = wdev->netdev; - -#else -int slsi_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) -{ -#endif - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - - if (WARN_ON(!dev)) - return -EINVAL; - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Dev name:%s\n", dev->name); - - slsi_stop_net_dev(sdev, dev); - slsi_netif_remove_rtlnl_locked(sdev, dev); - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - if (dev == sdev->netdev_ap) - rcu_assign_pointer(sdev->netdev_ap, NULL); - if (!sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]) - rcu_assign_pointer(sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN], sdev->netdev_ap); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - return 0; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) -int slsi_change_virtual_intf(struct wiphy *wiphy, - struct net_device *dev, - enum nl80211_iftype type, - struct vif_params *params) -{ -#else -int slsi_change_virtual_intf(struct wiphy *wiphy, - struct net_device *dev, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params) -{ -#endif - - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 0)) - SLSI_UNUSED_PARAMETER(flags); -#endif - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "type:%u, iftype:%d\n", type, ndev_vif->iftype); - - if (WARN_ON(ndev_vif->activated)) { - r = -EINVAL; - goto exit; - } - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: -#ifdef CONFIG_SCSC_WLAN_DEBUG - case NL80211_IFTYPE_MONITOR: -#endif - ndev_vif->iftype = type; - dev->ieee80211_ptr->iftype = type; - if (params) - dev->ieee80211_ptr->use_4addr = params->use_4addr; - break; - default: - r = -EINVAL; - break; - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -int slsi_add_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool pairwise, const u8 *mac_addr, - struct key_params *params) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = NULL; - int r = 0; - u16 key_type = FAPI_KEYTYPE_GROUP; - - if (WARN_ON(pairwise && !mac_addr)) - return -EINVAL; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "(key_index:%d, pairwise:%d, address:%pM, cipher:0x%.8X, key_len:%d," - "vif_type:%d)\n", key_index, pairwise, mac_addr, params->cipher, params->key_len, - ndev_vif->vif_type); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "vif not active\n"); - goto exit; - } - - if (params->cipher == WLAN_CIPHER_SUITE_PMK) { - r = slsi_mlme_set_pmk(sdev, dev, params->key, params->key_len); - goto exit; - } - - if (mac_addr && pairwise) { - /* All Pairwise Keys will have a peer record. */ - peer = slsi_get_peer_from_mac(sdev, dev, mac_addr); - if (peer) - mac_addr = peer->address; - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - /* Sta Group Key will use the peer address */ - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (peer) - mac_addr = peer->address; - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && !pairwise) - /* AP Group Key will use the Interface address */ - mac_addr = dev->dev_addr; - else { - r = -EINVAL; - goto exit; - } - - /*Treat WEP key as pairwise key*/ - if ((ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - ((params->cipher == WLAN_CIPHER_SUITE_WEP40) || - (params->cipher == WLAN_CIPHER_SUITE_WEP104)) && peer) { - u8 bc_mac_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "WEP Key: store key\n"); - r = slsi_mlme_set_key(sdev, dev, key_index, FAPI_KEYTYPE_WEP, bc_mac_addr, params); - if (r == FAPI_RESULTCODE_SUCCESS) { - /* if static ip is set before connection, after setting keys enable powersave. */ - if (ndev_vif->ipaddress) - slsi_mlme_powermgt(sdev, dev, ndev_vif->set_power_mode); - } else { - SLSI_NET_ERR(dev, "Error adding WEP key\n"); - } - goto exit; - } - - if (pairwise) { - key_type = FAPI_KEYTYPE_PAIRWISE; - if (WARN_ON(!peer)) { - r = -EINVAL; - goto exit; - } - } else if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { - key_type = FAPI_KEYTYPE_IGTK; - } - - if (WARN(!mac_addr, "mac_addr not defined\n")) { - r = -EINVAL; - goto exit; - } - if (!((ndev_vif->vif_type == FAPI_VIFTYPE_AP) && (key_index == 4))) { - r = slsi_mlme_set_key(sdev, dev, key_index, key_type, mac_addr, params); - if (r) { - SLSI_NET_ERR(dev, "error in adding key (key_type: %d)\n", key_type); - goto exit; - } - } - - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - ndev_vif->sta.eap_hosttag = 0xFFFF; - /* if static IP is set before connection, after setting keys enable powersave. */ - if (ndev_vif->ipaddress) - slsi_mlme_powermgt(sdev, dev, ndev_vif->set_power_mode); - } - - if (key_type == FAPI_KEYTYPE_GROUP) { - ndev_vif->sta.group_key_set = true; - ndev_vif->ap.cipher = params->cipher; - } else if (key_type == FAPI_KEYTYPE_PAIRWISE) { - if (peer) - peer->pairwise_key_set = true; - } - - if (peer) { - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - if (pairwise) { - if (params->cipher == WLAN_CIPHER_SUITE_SMS4) { /*WAPI */ - slsi_mlme_connect_resp(sdev, dev); - slsi_set_packet_filters(sdev, dev); - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - } - } - - if (ndev_vif->sta.gratuitous_arp_needed) { - ndev_vif->sta.gratuitous_arp_needed = false; - slsi_send_gratuitous_arp(sdev, dev); - } - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && pairwise) { - slsi_mlme_connected_resp(sdev, dev, peer->aid); - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - peer->connected_state = SLSI_STA_CONN_STATE_CONNECTED; - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO) - ndev_vif->ap.p2p_gc_keys_set = true; - } - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -int slsi_del_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool pairwise, const u8 *mac_addr) -{ - SLSI_UNUSED_PARAMETER(wiphy); - SLSI_UNUSED_PARAMETER(key_index); - SLSI_UNUSED_PARAMETER(pairwise); - SLSI_UNUSED_PARAMETER(mac_addr); - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_DELETEKEYS.request\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -int slsi_get_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool pairwise, const u8 *mac_addr, - void *cookie, - void (*callback)(void *cookie, struct key_params *)) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct key_params params; - -#define SLSI_MAX_KEY_SIZE 8 /*used only for AP case, so WAPI not considered*/ - u8 key_seq[SLSI_MAX_KEY_SIZE] = { 0 }; - int r = 0; - - SLSI_UNUSED_PARAMETER(mac_addr); - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_GET_KEY_SEQUENCE.request\n"); - return -EOPNOTSUPP; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "(key_index:%d, pairwise:%d, mac_addr:%pM, vif_type:%d)\n", key_index, - pairwise, mac_addr, ndev_vif->vif_type); - - if (!ndev_vif->activated) { - SLSI_NET_ERR(dev, "vif not active\n"); - r = -EINVAL; - goto exit; - } - - /* The get_key call is expected only for AP vif with Group Key type */ - if (FAPI_VIFTYPE_AP != ndev_vif->vif_type) { - SLSI_NET_ERR(dev, "Invalid vif type: %d\n", ndev_vif->vif_type); - r = -EINVAL; - goto exit; - } - if (pairwise) { - SLSI_NET_ERR(dev, "Invalid key type\n"); - r = -EINVAL; - goto exit; - } - - memset(¶ms, 0, sizeof(params)); - /* Update params with sequence number, key field would be updated NULL */ - params.key = NULL; - params.key_len = 0; - params.cipher = ndev_vif->ap.cipher; - if (!((ndev_vif->vif_type == FAPI_VIFTYPE_AP) && (key_index == 4))) { - r = slsi_mlme_get_key(sdev, dev, key_index, FAPI_KEYTYPE_GROUP, key_seq, ¶ms.seq_len); - - if (!r) { - params.seq = key_seq; - callback(cookie, ¶ms); - } - } -#undef SLSI_MAX_KEY_SIZE -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -static size_t slsi_strip_wsc_p2p_ie(const u8 *src_ie, size_t src_ie_len, u8 *dest_ie, bool strip_wsc, bool strip_p2p) -{ - const u8 *ie; - const u8 *next_ie; - size_t dest_ie_len = 0; - - if (!dest_ie || !(strip_p2p || strip_wsc)) - return dest_ie_len; - - for (ie = src_ie; (ie - src_ie) < src_ie_len; ie = next_ie) { - next_ie = ie + ie[1] + 2; - - if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] > 4) { - int i; - unsigned int oui = 0; - - for (i = 0; i < 4; i++) - oui = (oui << 8) | ie[5 - i]; - - if (strip_wsc && (oui == SLSI_WPS_OUI_PATTERN)) - continue; - if (strip_p2p && (oui == SLSI_P2P_OUI_PATTERN)) - continue; - } - - if (next_ie - src_ie <= src_ie_len) { - memcpy(dest_ie + dest_ie_len, ie, ie[1] + 2); - dest_ie_len += ie[1] + 2; - } - } - - return dest_ie_len; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request) -{ - struct net_device *dev = request->wdev->netdev; - -#else -int slsi_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request) -{ -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) */ - - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - u16 scan_type = FAPI_SCANTYPE_FULL_SCAN; - int r = 0; - u8 *scan_ie; - size_t scan_ie_len; - bool strip_wsc = false; - bool strip_p2p = false; - struct ieee80211_channel *channels[64]; - int i, chan_count = 0; - struct cfg80211_scan_info info = {.aborted = false}; -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - u8 mac_addr_mask[ETH_ALEN] = {0xFF}; -#endif - - if (WARN_ON(!request->wdev)) - return -EINVAL; - if (WARN_ON(!dev)) - return -EINVAL; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_WARN(dev, "not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - - /* Reject scan request if Group Formation is in progress */ - if (sdev->p2p_state == P2P_ACTION_FRAME_TX_RX) { - SLSI_NET_INFO(dev, "Scan received in P2P Action Frame Tx/Rx state - Reject\n"); - return -EBUSY; - } - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) { - SLSI_NET_INFO(dev, "Rejecting scan request as last scan is still running\n"); - r = -EBUSY; - goto exit; - } -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - if (ndev_vif->is_wips_running && (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - int ret = 0; - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "Scan invokes DRIVER_BCN_ABORT\n"); - ret = slsi_mlme_set_forward_beacon(sdev, dev, FAPI_ACTION_STOP); - - if (!ret) { - ret = slsi_send_forward_beacon_abort_vendor_event(sdev, - SLSI_FORWARD_BEACON_ABORT_REASON_SCANNING); - } - } -#endif - SLSI_NET_DBG3(dev, SLSI_CFG80211, "channels:%d, ssids:%d, ie_len:%d, vif_index:%d\n", request->n_channels, - request->n_ssids, (int)request->ie_len, ndev_vif->ifnum); - - for (i = 0; i < request->n_channels; i++) - channels[i] = request->channels[i]; - chan_count = request->n_channels; - - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - if (sdev->initial_scan) { - sdev->initial_scan = false; - scan_type = FAPI_SCANTYPE_INITIAL_SCAN; - } - ndev_vif->unsync.slsi_p2p_continuous_fullscan = false; - } - - /* Update scan timing for P2P social channels scan.*/ - if ((request->ie) && - cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, request->ie, request->ie_len) && - request->ssids && SLSI_IS_P2P_SSID(request->ssids[0].ssid, request->ssids[0].ssid_len)) { - /* In supplicant during joining procedure the P2P GO scan - * with GO's operating channel comes on P2P device. Hence added the - * check for n_channels as 1 - */ - if (!ndev_vif->drv_in_p2p_procedure) { - if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work)) { - cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work); - slsi_mlme_unset_channel_req(sdev, dev); - ndev_vif->driver_channel = 0; - } - } - if (request->n_channels == SLSI_P2P_SOCIAL_CHAN_COUNT || request->n_channels == 1) { - scan_type = FAPI_SCANTYPE_P2P_SCAN_SOCIAL; - ndev_vif->unsync.slsi_p2p_continuous_fullscan = false; - } else if (request->n_channels > SLSI_P2P_SOCIAL_CHAN_COUNT) { - if (!ndev_vif->unsync.slsi_p2p_continuous_fullscan) { - scan_type = FAPI_SCANTYPE_P2P_SCAN_FULL; - ndev_vif->unsync.slsi_p2p_continuous_fullscan = true; - } else { - int count = 0, chann = 0; - - scan_type = FAPI_SCANTYPE_P2P_SCAN_SOCIAL; - ndev_vif->unsync.slsi_p2p_continuous_fullscan = false; - for (i = 0; i < request->n_channels; i++) { - chann = channels[i]->hw_value & 0xFF; - if (chann == 1 || chann == 6 || chann == 11) { - channels[count] = request->channels[i]; - count++; - } - } - chan_count = count; - } - } - } - - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif) && (request->ie)) { - const u8 *ie; - - /* check HS2 related bits in extended capabilties (interworking, WNM,QoS Map, BSS transition) and set in MIB*/ - r = slsi_mlme_set_hs2_ext_cap(sdev, dev, request->ie, request->ie_len); - if (r) - goto exit; - - /* Supplicant adds wsc and p2p in Station scan at the end of scan request ie. - * for non-wps case remove both wps and p2p IEs - * for wps case remove only p2p IE - */ - - ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, request->ie, request->ie_len); - if (ie && ie[1] > SLSI_WPS_REQUEST_TYPE_POS && - ie[SLSI_WPS_REQUEST_TYPE_POS] == SLSI_WPS_REQUEST_TYPE_ENROLEE_INFO_ONLY) - strip_wsc = true; - - ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, request->ie, request->ie_len); - if (ie) - strip_p2p = true; - } - - if (strip_wsc || strip_p2p) { - scan_ie = kmalloc(request->ie_len, GFP_KERNEL); - if (!scan_ie) { - SLSI_NET_INFO(dev, "Out of memory for scan IEs\n"); - r = -ENOMEM; - goto exit; - } - scan_ie_len = slsi_strip_wsc_p2p_ie(request->ie, request->ie_len, scan_ie, strip_wsc, strip_p2p); - } else { - scan_ie = (u8 *)request->ie; - scan_ie_len = request->ie_len; - } - - /* Flush out any outstanding single scan timeout work */ - cancel_delayed_work(&ndev_vif->scan_timeout_work); - - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = false; - slsi_purge_scan_results(ndev_vif, SLSI_SCAN_HW_ID); - -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) - if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { - if (sdev->fw_mac_randomization_enabled) { - memcpy(sdev->scan_mac_addr, request->mac_addr, ETH_ALEN); - r = slsi_set_mac_randomisation_mask(sdev, request->mac_addr_mask); - if (!r) - sdev->scan_addr_set = 1; - } else { - SLSI_NET_INFO(dev, "Mac Randomization is not enabled in Firmware\n"); - sdev->scan_addr_set = 0; - } - } else -#endif - if (sdev->scan_addr_set) { - memset(mac_addr_mask, 0xFF, ETH_ALEN); - r = slsi_set_mac_randomisation_mask(sdev, mac_addr_mask); - sdev->scan_addr_set = 0; - } -#endif - - r = slsi_mlme_add_scan(sdev, - dev, - scan_type, - FAPI_REPORTMODE_REAL_TIME, - request->n_ssids, - request->ssids, - chan_count, - channels, - NULL, - scan_ie, - scan_ie_len, - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan); - - if (r != 0) { - if (r > 0) { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Nothing to be done\n"); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - cfg80211_scan_done(request, &info); -#else - cfg80211_scan_done(request, false); -#endif - r = 0; - } else { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "add_scan error: %d\n", r); - r = -EIO; - } - } else { - ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req = request; - - /* if delayed work is already scheduled, queue delayed work fails. So set - * requeue_timeout_work flag to enqueue delayed work in the timeout handler - */ - if (queue_delayed_work(sdev->device_wq, &ndev_vif->scan_timeout_work, - msecs_to_jiffies(SLSI_FW_SCAN_DONE_TIMEOUT_MSEC))) - ndev_vif->scan[SLSI_SCAN_HW_ID].requeue_timeout_work = false; - else - ndev_vif->scan[SLSI_SCAN_HW_ID].requeue_timeout_work = true; - - /* Update State only for scan in Device role */ - if (SLSI_IS_VIF_INDEX_P2P(ndev_vif) && (!SLSI_IS_P2P_GROUP_STATE(sdev))) { - if (scan_type == FAPI_SCANTYPE_P2P_SCAN_SOCIAL) - SLSI_P2P_STATE_CHANGE(sdev, P2P_SCANNING); - } else if (!SLSI_IS_VIF_INDEX_P2P(ndev_vif) && scan_ie_len) { - kfree(ndev_vif->probe_req_ies); - ndev_vif->probe_req_ies = kmalloc(request->ie_len, GFP_KERNEL); - if (!ndev_vif->probe_req_ies) /* Don't fail, continue as it would still work */ - ndev_vif->probe_req_ie_len = 0; - else { - ndev_vif->probe_req_ie_len = scan_ie_len; - memcpy(ndev_vif->probe_req_ies, scan_ie, scan_ie_len); - } - } - } - if (strip_p2p || strip_wsc) - kfree(scan_ie); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return r; -} - -int slsi_sched_scan_start(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_sched_scan_request *request) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int r; - u8 *scan_ie; - size_t scan_ie_len; - bool strip_wsc = false; - bool strip_p2p = false; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_ADD_SCAN.request\n"); - return -EOPNOTSUPP; - } - - /* Allow sched_scan only on wlan0. For P2PCLI interface, sched_scan might get requested following a - * wlan0 scan and its results being shared to sibling interfaces. Reject sched_scan for other interfaces. - */ - if (!SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - SLSI_NET_INFO(dev, "Scheduled scan req received on vif %d - Reject\n", ndev_vif->ifnum); - return -EINVAL; - } - - /* Unlikely to get a schedule scan while Group formation is in progress. - * In case it is requested, it will be rejected. - */ - if (sdev->p2p_state == P2P_ACTION_FRAME_TX_RX) { - SLSI_NET_INFO(dev, "Scheduled scan req received in P2P Action Frame Tx/Rx state - Reject\n"); - return -EBUSY; - } - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "channels:%d, ssids:%d, ie_len:%d, vif_index:%d\n", request->n_channels, - request->n_ssids, (int)request->ie_len, ndev_vif->ifnum); - - if (ndev_vif->scan[SLSI_SCAN_HW_ID].sched_req) { - r = -EBUSY; - goto exit; - } - - if (request->ie) { - const u8 *ie; - /* Supplicant adds wsc and p2p in Station scan at the end of scan request ie. - * Remove both wps and p2p IEs. - * Scheduled scan is not used for wsc, So no need to check for wsc request type - */ - - ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, request->ie, request->ie_len); - if (ie) - strip_wsc = true; - - ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, request->ie, request->ie_len); - if (ie) - strip_p2p = true; - } - - if (strip_wsc || strip_p2p) { - scan_ie = kmalloc(request->ie_len, GFP_KERNEL); - if (!scan_ie) { - SLSI_NET_INFO(dev, "Out of memory for scan IEs\n"); - r = -ENOMEM; - goto exit; - } - scan_ie_len = slsi_strip_wsc_p2p_ie(request->ie, request->ie_len, scan_ie, strip_wsc, strip_p2p); - } else { - scan_ie = (u8 *)request->ie; - scan_ie_len = request->ie_len; - } - - slsi_purge_scan_results(ndev_vif, SLSI_SCAN_SCHED_ID); - r = slsi_mlme_add_sched_scan(sdev, dev, request, scan_ie, scan_ie_len); - - if (strip_p2p || strip_wsc) - kfree(scan_ie); - - if (r != 0) { - if (r > 0) { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Nothing to be done\n"); - cfg80211_sched_scan_stopped(wiphy, request->reqid); - r = 0; - } else { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "add_scan error: %d\n", r); - r = -EIO; - } - } else { - ndev_vif->scan[SLSI_SCAN_SCHED_ID].sched_req = request; - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) -int slsi_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, u64 reqid) -{ -#else -int slsi_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) -{ -#endif - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int r = 0; - - SLSI_UNUSED_PARAMETER(reqid); - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - SLSI_NET_DBG1(dev, SLSI_CFG80211, "vif_index:%d", ndev_vif->ifnum); - if (!ndev_vif->scan[SLSI_SCAN_SCHED_ID].sched_req) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "No sched scan req\n"); - goto exit; - } - - r = slsi_mlme_del_scan(sdev, dev, (ndev_vif->ifnum << 8 | SLSI_SCAN_SCHED_ID), false); - - ndev_vif->scan[SLSI_SCAN_SCHED_ID].sched_req = NULL; - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return r; -} - -static void slsi_abort_hw_scan(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Abort on-going scan, vif_index:%d," - "ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req:%p\n", ndev_vif->ifnum, - ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req); - - if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) { - (void)slsi_mlme_del_scan(sdev, dev, ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID, false); - slsi_scan_complete(sdev, dev, SLSI_SCAN_HW_ID, false); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); -} - -int slsi_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct netdev_vif *ndev_p2p_vif; - u8 device_address[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - int r = 0; - u16 capability = WLAN_CAPABILITY_ESS; - struct slsi_peer *peer; - u16 prev_vif_type; - u32 action_frame_bmap; - struct net_device *p2p_dev; - const u8 *bssid; - struct ieee80211_channel *channel; - const u8 *connected_ssid = NULL; - u8 peer_address[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - u16 center_freq = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_CONNECT.request\n"); - return -EOPNOTSUPP; - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - capability = sme->privacy ? IEEE80211_PRIVACY_ON : IEEE80211_PRIVACY_OFF; -#else - if (sme->privacy) - capability |= WLAN_CAPABILITY_PRIVACY; -#endif - - SLSI_MUTEX_LOCK(sdev->start_stop_mutex); - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { - SLSI_WARN(sdev, "device not started yet (device_state:%d)\n", sdev->device_state); - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); - return -EINVAL; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (ndev_vif->sta.sta_bss) - SLSI_ETHER_COPY(peer_address, ndev_vif->sta.sta_bss->bssid); - - center_freq = sme->channel ? sme->channel->center_freq : 0; - - SLSI_NET_INFO(dev, "%.*s Freq=%d vifStatus=%d CurrBssid:%pM NewBssid:%pM Qinfo:%d ieLen:%d\n", - (int)sme->ssid_len, sme->ssid, center_freq, ndev_vif->sta.vif_status, - peer_address, sme->bssid, sdev->device_config.qos_info, (int)sme->ie_len); - -#ifdef CONFIG_SCSC_WIFILOGGER - SCSC_WLOG_PKTFATE_NEW_ASSOC(); - if (sme->bssid) { - SCSC_WLOG_DRIVER_EVENT(WLOG_NORMAL, WIFI_EVENT_ASSOCIATION_REQUESTED, 3, - WIFI_TAG_BSSID, ETH_ALEN, sme->bssid, - WIFI_TAG_SSID, sme->ssid_len, sme->ssid, - WIFI_TAG_CHANNEL, sizeof(u16), ¢er_freq); - // ?? WIFI_TAG_VENDOR_SPECIFIC, sizeof(RSSE), RSSE); - } -#endif - - if (SLSI_IS_HS2_UNSYNC_VIF(ndev_vif)) { - slsi_wlan_unsync_vif_deactivate(sdev, dev, true); - } else if (SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - SLSI_NET_ERR(dev, "Connect requested on incorrect vif\n"); - goto exit_with_error; - } - - if (WARN_ON(!sme->ssid)) - goto exit_with_error; - - if (WARN_ON(sme->ssid_len > IEEE80211_MAX_SSID_LEN)) - goto exit_with_error; - - if (sme->bssid) { - if ((SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) && (sdev->p2p_state == P2P_GROUP_FORMED_CLI)) { - p2p_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN); - if (p2p_dev) { - ndev_p2p_vif = netdev_priv(p2p_dev); - if (ndev_p2p_vif->sta.sta_bss) { - if (SLSI_ETHER_EQUAL(ndev_p2p_vif->sta.sta_bss->bssid, sme->bssid)) { - SLSI_NET_ERR(dev, "Connect Request Rejected\n"); - goto exit_with_error; - } - } - } - } - } - - if ((ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - /*reassociation*/ - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!peer)) - goto exit_with_error; - - if (!sme->bssid) { - SLSI_NET_ERR(dev, "Require bssid in reassoc but received null\n"); - goto exit_with_error; - } - if (!memcmp(peer->address, sme->bssid, ETH_ALEN)) { /*same bssid*/ - r = slsi_mlme_reassociate(sdev, dev); - if (r) { - SLSI_NET_ERR(dev, "Failed to reassociate : %d\n", r); - } else { - ndev_vif->sta.vif_status = SLSI_VIF_STATUS_CONNECTING; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - } - goto exit; - } else { /*different bssid*/ - connected_ssid = cfg80211_find_ie(WLAN_EID_SSID, ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len); - - if (!connected_ssid) { - SLSI_NET_ERR(dev, "Require ssid in roam but received null\n"); - goto exit_with_error; - } - - if (!memcmp(&connected_ssid[2], sme->ssid, connected_ssid[1])) { /*same ssid*/ - if (!sme->channel) { - SLSI_NET_ERR(dev, "Roaming has been rejected, as sme->channel is null\n"); - goto exit_with_error; - } - r = slsi_mlme_roam(sdev, dev, sme->bssid, sme->channel->center_freq); - if (r) { - SLSI_NET_ERR(dev, "Failed to roam : %d\n", r); - goto exit_with_error; - } - goto exit; - } else { - SLSI_NET_ERR(dev, "Connected but received connect to new ESS, without disconnect"); - goto exit_with_error; - } - } - } - /* Sta started case */ - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (SLSI_IS_VIF_INDEX_MHS(sdev, ndev_vif)) - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) { - SLSI_NET_ERR(dev, "Iftype: %d\n", ndev_vif->iftype); - goto exit_with_error; - } -#endif /*wifi sharing*/ - if (WARN_ON(ndev_vif->activated)) { - SLSI_NET_ERR(dev, "Vif is activated: %d\n", ndev_vif->activated); - goto exit_with_error; - } - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION && - ndev_vif->sta.vif_status != SLSI_VIF_STATUS_UNSPECIFIED) { - SLSI_NET_ERR(dev, "VIF status: %d\n", ndev_vif->sta.vif_status); - goto exit_with_error; - } - prev_vif_type = ndev_vif->vif_type; - - prev_vif_type = ndev_vif->vif_type; - switch (ndev_vif->iftype) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_STATION: - ndev_vif->iftype = NL80211_IFTYPE_STATION; - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - action_frame_bmap = SLSI_STA_ACTION_FRAME_BITMAP; -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - if (sdev->device_config.wes_mode) - action_frame_bmap |= SLSI_ACTION_FRAME_VENDOR_SPEC; -#endif - break; - case NL80211_IFTYPE_P2P_CLIENT: - slsi_p2p_group_start_remove_unsync_vif(sdev); - p2p_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2P); - if (p2p_dev) - SLSI_ETHER_COPY(device_address, p2p_dev->dev_addr); - action_frame_bmap = SLSI_ACTION_FRAME_PUBLIC; - break; - default: - SLSI_NET_ERR(dev, "Invalid Device Type: %d\n", ndev_vif->iftype); - goto exit_with_error; - } - - /* Initial Roaming checks done - assign vif type */ - ndev_vif->vif_type = FAPI_VIFTYPE_STATION; - - channel = sme->channel; - bssid = sme->bssid; - ndev_vif->sta.sta_bss = cfg80211_get_bss(wiphy, - sme->channel, - sme->bssid, - sme->ssid, - sme->ssid_len, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - IEEE80211_BSS_TYPE_ANY, -#else - capability, -#endif - capability); - if (!ndev_vif->sta.sta_bss) { - struct cfg80211_ssid ssid; - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "BSS info is not available - Perform scan\n"); - ssid.ssid_len = sme->ssid_len; - memcpy(ssid.ssid, sme->ssid, ssid.ssid_len); - r = slsi_mlme_connect_scan(sdev, dev, 1, &ssid, sme->channel); - if (r) { - SLSI_NET_ERR(dev, "slsi_mlme_connect_scan failed\n"); - goto exit; - } - ndev_vif->sta.sta_bss = cfg80211_get_bss(wiphy, - sme->channel, - sme->bssid, - sme->ssid, - sme->ssid_len, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - IEEE80211_BSS_TYPE_ANY, -#else - capability, -#endif - capability); - if (!ndev_vif->sta.sta_bss) { - SLSI_NET_ERR(dev, "cfg80211_get_bss(%.*s, %pM) Not found\n", (int)sme->ssid_len, sme->ssid, sme->bssid); - /*Set previous status in case of failure */ - ndev_vif->vif_type = prev_vif_type; - r = -ENOENT; - goto exit; - } - channel = ndev_vif->sta.sta_bss->channel; - bssid = ndev_vif->sta.sta_bss->bssid; - } else { - channel = ndev_vif->sta.sta_bss->channel; - bssid = ndev_vif->sta.sta_bss->bssid; - } - - ndev_vif->channel_type = NL80211_CHAN_NO_HT; - ndev_vif->chan = channel; - - if (slsi_mlme_add_vif(sdev, dev, dev->dev_addr, device_address) != 0) { - SLSI_NET_ERR(dev, "slsi_mlme_add_vif failed\n"); - goto exit_with_bss; - } - if (slsi_vif_activated(sdev, dev) != 0) { - SLSI_NET_ERR(dev, "slsi_vif_activated failed\n"); - goto exit_with_vif; - } - if (slsi_mlme_register_action_frame(sdev, dev, action_frame_bmap, action_frame_bmap) != 0) { - SLSI_NET_ERR(dev, "Action frame registration failed for bitmap value %d\n", action_frame_bmap); - goto exit_with_vif; - } - - r = slsi_set_boost(sdev, dev); - if (r != 0) - SLSI_NET_ERR(dev, "Rssi Boost set failed: %d\n", r); - - /* add_info_elements with Probe Req IEs. Proceed even if confirm fails for add_info as it would - * still work if the fw pre-join scan does not include the vendor IEs - */ - if (ndev_vif->probe_req_ies) { - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) { - if (sme->crypto.wpa_versions == 2) - ndev_vif->delete_probe_req_ies = true; /* Stored Probe Req can be deleted at vif - * deletion after WPA2 association - */ - else - /* Retain stored Probe Req at vif deletion until WPA2 connection to allow Probe req */ - ndev_vif->delete_probe_req_ies = false; - } else { - ndev_vif->delete_probe_req_ies = true; /* Delete stored Probe Req at vif deletion for STA */ - } - (void)slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_REQUEST, ndev_vif->probe_req_ies, - ndev_vif->probe_req_ie_len); - } - - /* Sometimes netif stack takes more time to initialize and any packet - * sent to stack would be dropped. This behavior is random in nature, - * so start the netif stack before sending out the connect req, it shall - * give enough time to netstack to initialize. - */ - netif_carrier_on(dev); - ndev_vif->sta.vif_status = SLSI_VIF_STATUS_CONNECTING; - -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG - if (sme->auth_type == NL80211_AUTHTYPE_SAE && (sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) { - const u8 *rsn; - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "N AKM Suites: : %1d\n", sme->crypto.n_akm_suites); - ndev_vif->sta.crypto.wpa_versions = 3; - rsn = cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len); - if (rsn) { - int pos; - - pos = 7 + 2 + (rsn[8] * 4) + 2; - ndev_vif->sta.crypto.akm_suites[0] = ((rsn[pos + 4] << 24) | (rsn[pos + 3] << 16) | (rsn[pos + 2] << 8) | (rsn[pos + 1])); - } - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "RSN IE: : %1d\n", ndev_vif->sta.crypto.akm_suites[0]); - } else { - ndev_vif->sta.crypto.wpa_versions = 0; - } -#endif - r = slsi_mlme_connect(sdev, dev, sme, channel, bssid); - if (r != 0) { - ndev_vif->sta.is_wps = false; - SLSI_NET_ERR(dev, "connect failed: %d\n", r); - netif_carrier_off(dev); - goto exit_with_vif; - } - - peer = slsi_peer_add(sdev, dev, (u8 *)bssid, SLSI_STA_PEER_QUEUESET + 1); - ndev_vif->sta.resp_id = 0; - - if (!peer) - goto exit_with_error; - - goto exit; - -exit_with_vif: - slsi_mlme_del_vif(sdev, dev); - slsi_vif_deactivated(sdev, dev); -exit_with_bss: - if (ndev_vif->sta.sta_bss) { - slsi_cfg80211_put_bss(wiphy, ndev_vif->sta.sta_bss); - ndev_vif->sta.sta_bss = NULL; - } -exit_with_error: - r = -EINVAL; -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); - return r; -} - -int slsi_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - int r = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "reason: %d, vif_index = %d, vif_type = %d\n", reason_code, - ndev_vif->ifnum, ndev_vif->vif_type); - - /* Assuming that the time it takes the firmware to disconnect is not significant - * as this function holds the locks until the MLME-DISCONNECT-IND comes back. - * Unless the MLME-DISCONNECT-CFM fails. - */ - if (!ndev_vif->activated) { - r = 0; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) - cfg80211_disconnected(dev, reason_code, NULL, 0, false, GFP_KERNEL); -#else - cfg80211_disconnected(dev, reason_code, NULL, 0, GFP_KERNEL); -#endif - SLSI_NET_INFO(dev, "Vif is already Deactivated\n"); - goto exit; - } - - peer = ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET]; - -#ifdef CONFIG_SCSC_WIFILOGGER - SCSC_WLOG_DRIVER_EVENT(WLOG_NORMAL, WIFI_EVENT_DISASSOCIATION_REQUESTED, 2, - WIFI_TAG_BSSID, ETH_ALEN, peer->address, - WIFI_TAG_REASON_CODE, sizeof(u16), &reason_code); -#endif - - switch (ndev_vif->vif_type) { - case FAPI_VIFTYPE_STATION: - { - slsi_reset_throughput_stats(dev); - /* Disconnecting spans several host firmware interactions so track the status - * so that the Host can ignore connect related signaling eg. MLME-CONNECT-IND - * now that it has triggered a disconnect. - */ - ndev_vif->sta.vif_status = SLSI_VIF_STATUS_DISCONNECTING; - - netif_carrier_off(dev); - if (peer->valid) - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - - /* MLME-DISCONNECT_CFM only means that the firmware has accepted the request it has not yet - * disconnected. Completion of the disconnect is indicated by MLME-DISCONNECT-IND, so have - * to wait for that before deleting the VIF. Also any new activities eg. connect can not yet - * be started on the VIF until the disconnection is completed. So the MLME function also handles - * waiting for the MLME-DISCONNECT-IND (if the CFM is successful) - */ - - r = slsi_mlme_disconnect(sdev, dev, peer->address, reason_code, true); - if (r != 0) - SLSI_NET_ERR(dev, "Disconnection returned with failure\n"); - /* Even if we fail to disconnect cleanly, tidy up. */ - r = slsi_handle_disconnect(sdev, dev, peer->address, 0, NULL, 0); - - break; - } - default: - SLSI_NET_WARN(dev, "Invalid - vif type:%d, device type:%d)\n", ndev_vif->vif_type, ndev_vif->iftype); - r = -EINVAL; - break; - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -int slsi_set_default_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool unicast, bool multicast) -{ - SLSI_UNUSED_PARAMETER(wiphy); - SLSI_UNUSED_PARAMETER(dev); - SLSI_UNUSED_PARAMETER(key_index); - SLSI_UNUSED_PARAMETER(unicast); - SLSI_UNUSED_PARAMETER(multicast); - /* Key is set in add_key. Nothing to do here */ - return 0; -} - -int slsi_config_default_mgmt_key(struct wiphy *wiphy, - struct net_device *dev, - u8 key_index) -{ - SLSI_UNUSED_PARAMETER(wiphy); - SLSI_UNUSED_PARAMETER(key_index); - SLSI_UNUSED_PARAMETER(dev); - - return 0; -} - -int slsi_set_wiphy_params(struct wiphy *wiphy, u32 changed) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int r = 0; - - SLSI_DBG1(sdev, SLSI_CFG80211, "slsi_set_wiphy_parms Frag Threshold = %d, RTS Threshold = %d", - wiphy->frag_threshold, wiphy->rts_threshold); - - if ((changed & WIPHY_PARAM_FRAG_THRESHOLD) && (wiphy->frag_threshold != -1)) { - r = slsi_set_uint_mib(sdev, NULL, SLSI_PSID_DOT11_FRAGMENTATION_THRESHOLD, wiphy->frag_threshold); - if (r != 0) { - SLSI_ERR(sdev, "Setting FRAG_THRESHOLD failed\n"); - return r; - } - } - - if ((changed & WIPHY_PARAM_RTS_THRESHOLD) && (wiphy->rts_threshold != -1)) { - r = slsi_set_uint_mib(sdev, NULL, SLSI_PSID_DOT11_RTS_THRESHOLD, wiphy->rts_threshold); - if (r != 0) { - SLSI_ERR(sdev, "Setting RTS_THRESHOLD failed\n"); - return r; - } - } - - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, - enum nl80211_tx_power_setting type, int mbm) -#else -int slsi_set_tx_power(struct wiphy *wiphy, - enum nl80211_tx_power_setting type, int mbm) -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) */ -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int r = 0; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - SLSI_UNUSED_PARAMETER(wdev); - SLSI_UNUSED_PARAMETER(type); -#endif - SLSI_UNUSED_PARAMETER(mbm); - SLSI_UNUSED_PARAMETER(sdev); - - r = -EOPNOTSUPP; - - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm) -#else -int slsi_get_tx_power(struct wiphy *wiphy, int *dbm) -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) */ -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int r = 0; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - SLSI_UNUSED_PARAMETER(wdev); -#endif - SLSI_UNUSED_PARAMETER(dbm); - SLSI_UNUSED_PARAMETER(sdev); - - r = -EOPNOTSUPP; - - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) -int slsi_del_station(struct wiphy *wiphy, struct net_device *dev, - struct station_del_parameters *del_params) -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) -int slsi_del_station(struct wiphy *wiphy, struct net_device *dev, - const u8 *mac) -#else -int slsi_del_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac) -#endif -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - int r = 0; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) - const u8 *mac = del_params->mac; -#endif - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "%pM, vifType:%d, vifIndex:%d vifActivated:%d ap.p2p_gc_keys_set = %d\n", - mac, ndev_vif->vif_type, ndev_vif->ifnum, ndev_vif->activated, ndev_vif->ap.p2p_gc_keys_set); - - /* Function is called by cfg80211 before the VIF is added */ - if (!ndev_vif->activated) - goto exit; - - if (FAPI_VIFTYPE_AP != ndev_vif->vif_type) { - r = -EINVAL; - goto exit; - } - /* MAC with NULL value will come in case of flushing VLANS . Ignore this.*/ - if (!mac) { - goto exit; - } else if (is_broadcast_ether_addr(mac)) { - int i = 0; - - while (i < SLSI_PEER_INDEX_MAX) { - peer = ndev_vif->peer_sta_record[i]; - if (peer && peer->valid) { - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - } - ++i; - } - - /* Note AP :: mlme_disconnect_request with broadcast mac address is - * not required. Other third party devices don't support this. Conclusively, - * BIP support is not present with AP - */ - - /* Free WPA and WMM IEs if present */ - slsi_clear_cached_ies(&ndev_vif->ap.cache_wpa_ie, &ndev_vif->ap.wpa_ie_len); - slsi_clear_cached_ies(&ndev_vif->ap.cache_wmm_ie, &ndev_vif->ap.wmm_ie_len); - - netif_carrier_off(dev); - - /* All STA related packets and info should already have been flushed */ - slsi_mlme_del_vif(sdev, dev); - slsi_vif_deactivated(sdev, dev); - ndev_vif->ipaddress = cpu_to_be32(0); - - if (ndev_vif->ap.p2p_gc_keys_set) { - slsi_wakeunlock(&sdev->wlan_wl); - ndev_vif->ap.p2p_gc_keys_set = false; - } - } else { - peer = slsi_get_peer_from_mac(sdev, dev, mac); - if (peer) { /* To handle race condition when disconnect_req is sent before procedure_strted_ind and before mlme-connected_ind*/ - if (peer->connected_state == SLSI_STA_CONN_STATE_CONNECTING) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "SLSI_STA_CONN_STATE_CONNECTING : mlme-disconnect-req dropped at driver\n"); - goto exit; - } - if (peer->is_wps) { - /* To inter-op with Intel STA in P2P cert need to discard the deauth after successful WPS handshake as a P2P GO */ - SLSI_NET_INFO(dev, "DISCONNECT after WPS : mlme-disconnect-req dropped at driver\n"); - goto exit; - } - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - r = slsi_mlme_disconnect(sdev, dev, peer->address, WLAN_REASON_DEAUTH_LEAVING, true); - if (r != 0) - SLSI_NET_ERR(dev, "Disconnection returned with failure\n"); - /* Even if we fail to disconnect cleanly, tidy up. */ - r = slsi_handle_disconnect(sdev, dev, peer->address, WLAN_REASON_DEAUTH_LEAVING, NULL, 0); - } - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) -int slsi_get_station(struct wiphy *wiphy, struct net_device *dev, - const u8 *mac, struct station_info *sinfo) -#else -int slsi_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac, struct station_info *sinfo) -#endif -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - int r = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - r = -EINVAL; - goto exit; - } - - peer = slsi_get_peer_from_mac(sdev, dev, mac); - if (!peer) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "%pM : Not Found\n", mac); - r = -EINVAL; - goto exit; - } - - if (((ndev_vif->iftype == NL80211_IFTYPE_STATION && !(ndev_vif->sta.roam_in_progress)) || - ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT)) { - /*Read MIB and fill into the peer.sinfo*/ - r = slsi_mlme_get_sinfo_mib(sdev, dev, peer); - if (r) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "failed to read Station Info Error:%d\n", r); - goto exit; - } - } - - *sinfo = peer->sinfo; - sinfo->generation = ndev_vif->cfg80211_sinfo_generation; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - SLSI_NET_DBG1(dev, SLSI_CFG80211, "%pM, tx:%d, txbytes:%llu, rx:%d, rxbytes:%llu tx_fail:%d tx_retry:%d\n", - mac, - peer->sinfo.tx_packets, - peer->sinfo.tx_bytes, - peer->sinfo.rx_packets, - peer->sinfo.rx_bytes, - peer->sinfo.tx_failed, - peer->sinfo.tx_retries); -#else - SLSI_NET_DBG1(dev, SLSI_CFG80211, "%pM, tx:%d, txbytes:%d, rx:%d, rxbytes:%d tx_fail:%d tx_retry:%d\n", - mac, - peer->sinfo.tx_packets, - peer->sinfo.tx_bytes, - peer->sinfo.rx_packets, - peer->sinfo.rx_bytes, - peer->sinfo.tx_failed, - peer->sinfo.tx_retries); -#endif - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -int slsi_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, - bool enabled, int timeout) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = -EINVAL; - u16 pwr_mode = enabled ? FAPI_POWERMANAGEMENTMODE_POWER_SAVE : FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE; - - SLSI_UNUSED_PARAMETER(timeout); - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_POWERMGT.request\n"); - return -EOPNOTSUPP; - } - - if (slsi_is_rf_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, RF test does not support.\n"); - return -EOPNOTSUPP; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "enabled:%d, vif_type:%d, vif_index:%d\n", enabled, ndev_vif->vif_type, - ndev_vif->ifnum); - - if ((ndev_vif->activated) && (ndev_vif->vif_type == FAPI_VIFTYPE_STATION)) { - ndev_vif->set_power_mode = pwr_mode; - r = slsi_mlme_powermgt(sdev, dev, pwr_mode); - } else { - r = 0; - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 18)) -int slsi_tdls_oper(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, enum nl80211_tdls_operation oper) -#else -int slsi_tdls_oper(struct wiphy *wiphy, struct net_device *dev, u8 *peer, enum nl80211_tdls_operation oper) -#endif -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "oper:%d, vif_type:%d, vif_index:%d\n", oper, ndev_vif->vif_type, - ndev_vif->ifnum); - - if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) - return -ENOTSUPP; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((!ndev_vif->activated) || SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - r = -ENOTSUPP; - goto exit; - } - - switch (oper) { - case NL80211_TDLS_DISCOVERY_REQ: - SLSI_NET_DBG1(dev, SLSI_CFG80211, "NL80211_TDLS_DISCOVERY_REQ\n"); - r = slsi_mlme_tdls_action(sdev, dev, peer, FAPI_TDLSACTION_DISCOVERY, 0, 0); - break; - case NL80211_TDLS_SETUP: - r = slsi_mlme_tdls_action(sdev, dev, peer, FAPI_TDLSACTION_SETUP, 0, 0); - break; - case NL80211_TDLS_TEARDOWN: - r = slsi_mlme_tdls_action(sdev, dev, peer, FAPI_TDLSACTION_TEARDOWN, 0, 0); - break; - default: - r = -EOPNOTSUPP; - goto exit; - } -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) -int slsi_set_qos_map(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_qos_map *qos_map) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - int r = 0; - - /* Cleaning up is inherently taken care by driver */ - if (!qos_map) - return r; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - r = -EINVAL; - goto exit; - } - - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) { - r = -EINVAL; - goto exit; - } - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "Set QoS Map\n"); - peer = ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET]; - if (!peer || !peer->valid) { - r = -EINVAL; - goto exit; - } - - memcpy(&peer->qos_map, qos_map, sizeof(struct cfg80211_qos_map)); - peer->qos_map_set = true; - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -#ifdef CONFIG_SCSC_WLAN_DEBUG -int slsi_set_monitor_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev; - struct netdev_vif *ndev_vif; - - SLSI_DBG1(sdev, SLSI_CFG80211, "channel (freq:%u)\n", chandef->chan->center_freq); - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, SLSI_NET_INDEX_WLAN); - if (!dev) { - SLSI_ERR(sdev, "netdev No longer exists\n"); - rcu_read_unlock(); - return -EINVAL; - } - ndev_vif = netdev_priv(dev); - rcu_read_unlock(); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (slsi_test_sap_configure_monitor_mode(sdev, dev, chandef) != 0) { - SLSI_ERR(sdev, "set Monitor channel failed\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return 0; -} -#endif -#endif -int slsi_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) -{ - SLSI_UNUSED_PARAMETER(wow); - - return 0; -} - -int slsi_resume(struct wiphy *wiphy) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - - /* Scheduling the IO thread */ -/* (void)slsi_hip_run_bh(sdev); */ - SLSI_UNUSED_PARAMETER(sdev); - - return 0; -} - -int slsi_set_pmksa(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_pmksa *pmksa) -{ - SLSI_UNUSED_PARAMETER(wiphy); - SLSI_UNUSED_PARAMETER(dev); - SLSI_UNUSED_PARAMETER(pmksa); - return 0; -} - -int slsi_del_pmksa(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_pmksa *pmksa) -{ - SLSI_UNUSED_PARAMETER(wiphy); - SLSI_UNUSED_PARAMETER(dev); - SLSI_UNUSED_PARAMETER(pmksa); - return 0; -} - -int slsi_flush_pmksa(struct wiphy *wiphy, struct net_device *dev) -{ - SLSI_UNUSED_PARAMETER(wiphy); - SLSI_UNUSED_PARAMETER(dev); - return 0; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_remain_on_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, - struct ieee80211_channel *chan, - unsigned int duration, - u64 *cookie) -{ - struct net_device *dev = wdev->netdev; - -#else -int slsi_remain_on_channel(struct wiphy *wiphy, - struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type, - unsigned int duration, - u64 *cookie) -{ -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) */ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - - SLSI_MUTEX_LOCK(sdev->start_stop_mutex); - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { - SLSI_WARN(sdev, "device not started yet (device_state:%d)\n", sdev->device_state); - goto exit_with_error; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "channel freq = %d, duration = %d, vif_type = %d, vif_index = %d," - "sdev->p2p_state = %s\n", chan->center_freq, duration, ndev_vif->vif_type, ndev_vif->ifnum, - slsi_p2p_state_text(sdev->p2p_state)); - if (!SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - SLSI_NET_ERR(dev, "Invalid vif type\n"); - goto exit_with_error; - } - - if (SLSI_IS_P2P_GROUP_STATE(sdev)) { - slsi_assign_cookie_id(cookie, &ndev_vif->unsync.roc_cookie); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL); - cfg80211_remain_on_channel_expired(wdev, *cookie, chan, GFP_KERNEL); -#else - cfg80211_ready_on_channel(dev, *cookie, chan, channel_type, duration, GFP_KERNEL); - cfg80211_remain_on_channel_expired(dev, *cookie, chan, channel_type, GFP_KERNEL); -#endif - goto exit; - } - - /* Unsync vif will be required, cancel any pending work of its deletion */ - cancel_delayed_work(&ndev_vif->unsync.del_vif_work); - - /* Ideally, there should not be any ROC work pending. However, supplicant can send back to back ROC in a race scenario as below. - * If action frame is received while P2P social scan, the response frame tx is delayed till scan completes. After scan completion, - * frame tx is done and ROC is started. Upon frame tx status, supplicant sends another ROC without cancelling the previous one. - */ - cancel_delayed_work(&ndev_vif->unsync.roc_expiry_work); - - if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work)) - cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work); - - /* If action frame tx is in progress and ROC comes, then it would mean action frame tx was done in ROC and - * frame tx ind is awaited, don't change state. Also allow back to back ROC in case it comes. - */ - if ((sdev->p2p_state == P2P_ACTION_FRAME_TX_RX) || (sdev->p2p_state == P2P_LISTENING)) { - goto exit_with_roc; - } - - /* Unsync vif activation: Possible P2P state at this point is P2P_IDLE_NO_VIF or P2P_IDLE_VIF_ACTIVE */ - if (sdev->p2p_state == P2P_IDLE_NO_VIF) { - if (slsi_p2p_vif_activate(sdev, dev, chan, duration, true) != 0) - goto exit_with_error; - } else if (sdev->p2p_state == P2P_IDLE_VIF_ACTIVE) { - /* Configure Probe Response IEs in firmware if they have changed */ - if (ndev_vif->unsync.ies_changed) { - u16 purpose = FAPI_PURPOSE_PROBE_RESPONSE; - - if (slsi_mlme_add_info_elements(sdev, dev, purpose, ndev_vif->unsync.probe_rsp_ies, ndev_vif->unsync.probe_rsp_ies_len) != 0) { - SLSI_NET_ERR(dev, "Probe Rsp IEs setting failed\n"); - goto exit_with_vif; - } - ndev_vif->unsync.ies_changed = false; - } - /* Channel Setting - Don't set if already on same channel */ - if (ndev_vif->driver_channel != chan->hw_value) { - if (slsi_mlme_set_channel(sdev, dev, chan, SLSI_FW_CHANNEL_DURATION_UNSPECIFIED, 0, 0) != 0) { - SLSI_NET_ERR(dev, "Channel setting failed\n"); - goto exit_with_vif; - } else { - ndev_vif->chan = chan; - ndev_vif->driver_channel = chan->hw_value; - } - } - } else { - SLSI_NET_ERR(dev, "Driver in incorrect P2P state (%s)", slsi_p2p_state_text(sdev->p2p_state)); - goto exit_with_error; - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 9)) - ndev_vif->channel_type = channel_type; -#endif - - SLSI_P2P_STATE_CHANGE(sdev, P2P_LISTENING); - -exit_with_roc: - /* Cancel remain on channel is sent to the supplicant 10ms before the duration - *This is to avoid the race condition of supplicant sending cancel remain on channel and - *drv sending cancel_remain on channel because of roc expiry. - *This race condition causes delay to the next p2p search - */ - queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.roc_expiry_work, - msecs_to_jiffies(duration - SLSI_P2P_ROC_EXTRA_MSEC)); - - slsi_assign_cookie_id(cookie, &ndev_vif->unsync.roc_cookie); - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Cookie = 0x%llx\n", *cookie); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL); -#else - cfg80211_ready_on_channel(dev, *cookie, chan, channel_type, duration, GFP_KERNEL); -#endif - - goto exit; - -exit_with_vif: - slsi_p2p_vif_deactivate(sdev, dev, true); -exit_with_error: - r = -EINVAL; -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_cancel_remain_on_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, - u64 cookie) -{ - struct net_device *dev = wdev->netdev; - -#else -int slsi_cancel_remain_on_channel(struct wiphy *wiphy, - struct net_device *dev, - u64 cookie) -{ -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) */ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int r = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Cookie = 0x%llx, vif_type = %d, vif_index = %d, sdev->p2p_state = %s," - "ndev_vif->ap.p2p_gc_keys_set = %d, ndev_vif->unsync.roc_cookie = 0x%llx\n", cookie, - ndev_vif->vif_type, ndev_vif->ifnum, slsi_p2p_state_text(sdev->p2p_state), - ndev_vif->ap.p2p_gc_keys_set, ndev_vif->unsync.roc_cookie); - - if (!SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - SLSI_NET_ERR(dev, "Invalid vif type\n"); - r = -EINVAL; - goto exit; - } - - if (!((sdev->p2p_state == P2P_LISTENING) || (sdev->p2p_state == P2P_ACTION_FRAME_TX_RX))) { - goto exit; - } - - if (sdev->p2p_state == P2P_ACTION_FRAME_TX_RX && ndev_vif->mgmt_tx_data.exp_frame != SLSI_P2P_PA_INVALID) { - /* Reset the expected action frame as procedure got completed */ - SLSI_INFO(sdev, "Action frame (%s) was not received\n", slsi_p2p_pa_subtype_text(ndev_vif->mgmt_tx_data.exp_frame)); - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - } - - cancel_delayed_work(&ndev_vif->unsync.roc_expiry_work); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_remain_on_channel_expired(&ndev_vif->wdev, ndev_vif->unsync.roc_cookie, ndev_vif->chan, GFP_KERNEL); -#else - cfg80211_remain_on_channel_expired(ndev_vif->wdev.netdev, ndev_vif->unsync.roc_cookie, - ndev_vif->chan, ndev_vif->channel_type, GFP_KERNEL); -#endif - if (!ndev_vif->drv_in_p2p_procedure) { - if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work)) - cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work); - queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.unset_channel_expiry_work, - msecs_to_jiffies(SLSI_P2P_UNSET_CHANNEL_EXTRA_MSEC)); - } - /* Queue work to delete unsync vif */ - slsi_p2p_queue_unsync_vif_del_work(ndev_vif, SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC); - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -int slsi_change_bss(struct wiphy *wiphy, struct net_device *dev, - struct bss_parameters *params) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int r = 0; - - SLSI_UNUSED_PARAMETER(params); - SLSI_UNUSED_PARAMETER(sdev); - - return r; -} - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 5, 0)) -int slsi_set_channel(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - - SLSI_UNUSED_PARAMETER(sdev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "channel_type:%u, freq:%u, vif_index:%d, vif_type:%d\n", channel_type, - chan->center_freq, ndev_vif->ifnum, ndev_vif->vif_type); - if (WARN_ON(ndev_vif->activated)) { - r = -EINVAL; - goto exit; - } - - ndev_vif->channel_type = channel_type; - ndev_vif->chan = chan; - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} -#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 5, 0)) */ - -static void slsi_ap_start_obss_scan(struct slsi_dev *sdev, struct net_device *dev, struct netdev_vif *ndev_vif) -{ - struct cfg80211_ssid ssids; - struct ieee80211_channel *channel; - int n_ssids = 1, n_channels = 1, i; - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "channel %u\n", ndev_vif->chan->hw_value); - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - ssids.ssid_len = 0; - for (i = 0; i < IEEE80211_MAX_SSID_LEN; i++) - ssids.ssid[i] = 0x00; /* Broadcast SSID */ - - channel = ieee80211_get_channel(sdev->wiphy, ndev_vif->chan->center_freq); - - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = true; - (void)slsi_mlme_add_scan(sdev, - dev, - FAPI_SCANTYPE_OBSS_SCAN, - FAPI_REPORTMODE_REAL_TIME, - n_ssids, - &ssids, - n_channels, - &channel, - NULL, - NULL, /* No IEs */ - 0, - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan /* Wait for scan_done_ind */); - - slsi_ap_obss_scan_done_ind(dev, ndev_vif); - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = false; - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); -} - -static int slsi_ap_start_validate(struct net_device *dev, struct slsi_dev *sdev, struct cfg80211_ap_settings *settings) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - if (SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - SLSI_NET_ERR(dev, "AP start requested on incorrect vif\n"); - goto exit_with_error; - } - - if (!settings->ssid_len || !settings->ssid) { - SLSI_NET_ERR(dev, "SSID not provided\n"); - goto exit_with_error; - } - - if (!settings->beacon.head_len || !settings->beacon.head) { - SLSI_NET_ERR(dev, "Beacon not provided\n"); - goto exit_with_error; - } - - if (!settings->beacon_interval) { - SLSI_NET_ERR(dev, "Beacon Interval not provided\n"); - goto exit_with_error; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - ndev_vif->chandef = &settings->chandef; - ndev_vif->chan = ndev_vif->chandef->chan; -#endif - if (WARN_ON(!ndev_vif->chan)) - goto exit_with_error; - - if (WARN_ON(ndev_vif->activated)) - goto exit_with_error; - - if (WARN_ON((ndev_vif->iftype != NL80211_IFTYPE_AP) && (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO))) - goto exit_with_error; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if ((ndev_vif->chan->hw_value <= 14) && (!sdev->fw_SoftAp_2g_40mhz_enabled) && - (ndev_vif->chandef->width == NL80211_CHAN_WIDTH_40)) { - SLSI_NET_ERR(dev, "Configuration error: 40 MHz on 2.4 GHz is not supported. Channel_no: %d Channel_width: %d\n", ndev_vif->chan->hw_value, slsi_get_chann_info(sdev, ndev_vif->chandef)); - goto exit_with_error; - } -#else - if ((ndev_vif->chan->hw_value <= 14) && (!sdev->fw_SoftAp_2g_40mhz_enabled) && - (ndev_vif->channel_type > NL80211_CHAN_HT20)) { - SLSI_NET_ERR(dev, "Configuration error: 40 MHz on 2.4 GHz is not supported. Channel_no: %d Channel_width: %d\n", ndev_vif->chan->hw_value, slsi_get_chann_info(sdev, ndev_vif->channel_type)); - goto exit_with_error; - } -#endif - - return 0; - -exit_with_error: - return -EINVAL; -} - -static int slsi_get_max_bw_mhz(struct slsi_dev *sdev, u16 prim_chan_cf) -{ - int i; - struct ieee80211_regdomain *regd = sdev->device_config.domain_info.regdomain; - - if (!regd) { - SLSI_WARN(sdev, "NO regdomain info\n"); - return 0; - } - - for (i = 0; i < regd->n_reg_rules; i++) { - if ((regd->reg_rules[i].freq_range.start_freq_khz / 1000 <= prim_chan_cf - 10) && - (regd->reg_rules[i].freq_range.end_freq_khz / 1000 >= prim_chan_cf + 10)) - return regd->reg_rules[i].freq_range.max_bandwidth_khz / 1000; - } - - SLSI_WARN(sdev, "Freq(%d) not found in regdomain\n", prim_chan_cf); - return 0; -} - -int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *settings) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct net_device *wlan_dev; - u8 device_address[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - int r = 0; - const u8 *wpa_ie_pos = NULL; - size_t wpa_ie_len = 0; - const u8 *wmm_ie_pos = NULL; - size_t wmm_ie_len = 0; - const u8 *country_ie = NULL; - char alpha2[SLSI_COUNTRY_CODE_LEN]; - bool append_vht_ies = false; - const u8 *ie; -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - int wifi_sharing_channel_switched = 0; - struct netdev_vif *ndev_sta_vif; - int invalid_channel = 0; -#endif - int skip_indoor_check_for_wifi_sharing = 0; - u8 *ds_params_ie = NULL; - struct ieee80211_mgmt *mgmt; - u16 beacon_ie_head_len; - u8 *ht_operation_ie = NULL; - struct ieee80211_channel *channel = NULL; - int indoor_channel = 0; - int i; - u32 chan_flags; - u16 center_freq; - - SLSI_MUTEX_LOCK(sdev->start_stop_mutex); - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { - SLSI_WARN(sdev, "device not started yet (device_state:%d)\n", sdev->device_state); - r = -EINVAL; - goto exit_with_start_stop_mutex; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - /* Abort any ongoing wlan scan. */ - wlan_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - if (wlan_dev) - slsi_abort_hw_scan(sdev, wlan_dev); - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "AP frequency received: %d\n", settings->chandef.chan->center_freq); - mgmt = (struct ieee80211_mgmt *)settings->beacon.head; - beacon_ie_head_len = settings->beacon.head_len - ((u8 *)mgmt->u.beacon.variable - (u8 *)mgmt); -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - ndev_sta_vif = netdev_priv(wlan_dev); - if (SLSI_IS_VIF_INDEX_MHS(sdev, ndev_vif)) { - if (ndev_sta_vif) { - SLSI_MUTEX_LOCK(ndev_sta_vif->vif_mutex); - if ((ndev_sta_vif->activated) && (ndev_sta_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTING || - ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - invalid_channel = slsi_select_wifi_sharing_ap_channel(wiphy, dev, settings, sdev, - &wifi_sharing_channel_switched); - skip_indoor_check_for_wifi_sharing = 1; - if (invalid_channel) { - SLSI_NET_ERR(dev, "Rejecting AP start req at host (invalid channel)\n"); - SLSI_MUTEX_UNLOCK(ndev_sta_vif->vif_mutex); - r = -EINVAL; - goto exit_with_vif_mutex; - } - } - SLSI_MUTEX_UNLOCK(ndev_sta_vif->vif_mutex); - } - } -#endif - - memset(&ndev_vif->ap, 0, sizeof(ndev_vif->ap)); - /* Initialise all allocated peer structures to remove old data. */ - /*slsi_netif_init_all_peers(sdev, dev);*/ - - /* Reg domain changes */ - country_ie = cfg80211_find_ie(WLAN_EID_COUNTRY, settings->beacon.tail, settings->beacon.tail_len); - if (country_ie) { - country_ie += 2; - memcpy(alpha2, country_ie, SLSI_COUNTRY_CODE_LEN); - if (memcmp(sdev->device_config.domain_info.regdomain->alpha2, alpha2, SLSI_COUNTRY_CODE_LEN - 1) != 0) { - if (slsi_set_country_update_regd(sdev, alpha2, SLSI_COUNTRY_CODE_LEN) != 0) { - r = -EINVAL; - goto exit_with_vif_mutex; - } - } - } - if (!skip_indoor_check_for_wifi_sharing && sdev->band_5g_supported && - ((settings->chandef.chan->center_freq / 1000) == 5)) { - channel = ieee80211_get_channel(sdev->wiphy, settings->chandef.chan->center_freq); - if (!channel) { - SLSI_ERR(sdev, "Invalid frequency %d used to start AP. Channel not found\n", - settings->chandef.chan->center_freq); - r = -EINVAL; - goto exit_with_vif_mutex; - } - if (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO) { - if ((channel->flags) & (IEEE80211_CHAN_INDOOR_ONLY)) { - chan_flags = (IEEE80211_CHAN_INDOOR_ONLY | IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_DISABLED | -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13) - IEEE80211_CHAN_PASSIVE_SCAN -#else - IEEE80211_CHAN_NO_IR -#endif - ); - - for (i = 0; i < wiphy->bands[NL80211_BAND_5GHZ]->n_channels; i++) { - if (!(wiphy->bands[NL80211_BAND_5GHZ]->channels[i].flags & chan_flags)) { - center_freq = wiphy->bands[NL80211_BAND_5GHZ]->channels[i].center_freq; - settings->chandef.chan = ieee80211_get_channel(wiphy, center_freq); - settings->chandef.center_freq1 = center_freq; - SLSI_DBG1(sdev, SLSI_CFG80211, "ap valid frequency:%d,chan_flags:%x\n", - center_freq, - wiphy->bands[NL80211_BAND_5GHZ]->channels[i].flags); - indoor_channel = 1; - break; - } - } - if (indoor_channel == 0) { - SLSI_ERR(sdev, "No valid channel found to start the AP"); - r = -EINVAL; - goto exit_with_vif_mutex; - } - } - } - } - - r = slsi_ap_start_validate(dev, sdev, settings); - if (r != 0) - goto exit_with_vif_mutex; - - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO) { - struct net_device *p2p_dev; - - slsi_p2p_group_start_remove_unsync_vif(sdev); - p2p_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2P); - SLSI_ETHER_COPY(device_address, p2p_dev->dev_addr); - if (keep_alive_period != SLSI_P2PGO_KEEP_ALIVE_PERIOD_SEC) - if (slsi_set_uint_mib(sdev, NULL, SLSI_PSID_UNIFI_MLMEGO_KEEP_ALIVE_TIMEOUT, - keep_alive_period) != 0) { - SLSI_NET_ERR(dev, "P2PGO Keep Alive MIB set failed"); - r = -EINVAL; - goto exit_with_vif_mutex; - } - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - SLSI_NET_DBG1(dev, SLSI_MLME, "Channel: %d, Maximum bandwidth: %d\n", ndev_vif->chandef->chan->hw_value, - slsi_get_max_bw_mhz(sdev, ndev_vif->chandef->chan->center_freq)); - /* 11ac configuration (5GHz and VHT) */ - if ((ndev_vif->chandef->chan->hw_value >= 36) && (ndev_vif->chandef->chan->hw_value < 165) && - (sdev->fw_vht_enabled) && sdev->allow_switch_80_mhz && - (slsi_get_max_bw_mhz(sdev, ndev_vif->chandef->chan->center_freq) >= 80)) { - u16 oper_chan = ndev_vif->chandef->chan->hw_value; - append_vht_ies = true; - ndev_vif->chandef->width = NL80211_CHAN_WIDTH_80; - - SLSI_NET_DBG1(dev, SLSI_MLME, "5 GHz- Include VHT\n"); - if ((oper_chan >= 36) && (oper_chan <= 48)) - ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(42, NL80211_BAND_5GHZ); - else if ((oper_chan >= 149) && (oper_chan <= 161)) - ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(155, NL80211_BAND_5GHZ); -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - /* In wifi sharing case, AP can start on STA channel even though it is DFS channel*/ - if (wifi_sharing_channel_switched == 1) { - if ((oper_chan >= 52) && (oper_chan <= 64)) - ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(58, - NL80211_BAND_5GHZ); - else if ((oper_chan >= 100) && (oper_chan <= 112)) - ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(106, - NL80211_BAND_5GHZ); - else if ((oper_chan >= 116) && (oper_chan <= 128)) - ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(122, - NL80211_BAND_5GHZ); - else if ((oper_chan >= 132) && (oper_chan <= 144)) - ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(138, - NL80211_BAND_5GHZ); - } -#endif - } else if (sdev->fw_ht_enabled && sdev->allow_switch_40_mhz && - slsi_get_max_bw_mhz(sdev, ndev_vif->chandef->chan->center_freq) >= 40 && - ((ndev_vif->chandef->chan->hw_value < 165 && ndev_vif->chandef->chan->hw_value >= 36) || - (ndev_vif->chandef->chan->hw_value < 12 && sdev->fw_SoftAp_2g_40mhz_enabled && - ndev_vif->iftype == NL80211_IFTYPE_P2P_GO))) { - /* HT40 configuration (5GHz/2GHz and HT) */ - u16 oper_chan = ndev_vif->chandef->chan->hw_value; - u8 bw_40_minus_channels[] = { 40, 48, 153, 161, 5, 6, 7, 8, 9, 10, 11 }; -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - u8 bw_40_minus_dfs_channels[] = { 144, 136, 128, 120, 112, 104, 64, 56 }; -#endif - u8 ch; - - ndev_vif->chandef->width = NL80211_CHAN_WIDTH_40; - ndev_vif->chandef->center_freq1 = ndev_vif->chandef->chan->center_freq + 10; - for (ch = 0; ch < ARRAY_SIZE(bw_40_minus_channels); ch++) - if (oper_chan == bw_40_minus_channels[ch]) { - ndev_vif->chandef->center_freq1 = ndev_vif->chandef->chan->center_freq - 10; - break; - } - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (wifi_sharing_channel_switched == 1) { - for (ch = 0; ch < ARRAY_SIZE(bw_40_minus_dfs_channels); ch++) - if (oper_chan == bw_40_minus_dfs_channels[ch]) { - ndev_vif->chandef->center_freq1 = ndev_vif->chandef->chan->center_freq - 10; - break; - } - } -#endif - } -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (slsi_check_channelization(sdev, ndev_vif->chandef, wifi_sharing_channel_switched) != 0) { -#else - if (slsi_check_channelization(sdev, ndev_vif->chandef, 0) != 0) { -#endif -#else - if (slsi_check_channelization(sdev, ndev_vif->channel_type) != 0) { -#endif - r = -EINVAL; - goto exit_with_vif_mutex; - } - - if (ndev_vif->iftype == NL80211_IFTYPE_AP) { - /* Legacy AP */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (ndev_vif->chandef->width == NL80211_CHAN_WIDTH_20) -#else - if (ndev_vif->channel_type == NL80211_CHAN_HT20) -#endif - slsi_ap_start_obss_scan(sdev, dev, ndev_vif); - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (ndev_vif->chandef->width <= NL80211_CHAN_WIDTH_20) { - /* Enable LDPC, SGI20 and SGI40 for both SoftAP & P2PGO if firmware supports */ - if (cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, settings->beacon.tail, settings->beacon.tail_len)) { - u8 enforce_ht_cap1 = sdev->fw_ht_cap[0] & (IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_SGI_20); - u8 enforce_ht_cap2 = sdev->fw_ht_cap[1] & (IEEE80211_HT_CAP_RX_STBC >> 8); - - slsi_modify_ies(dev, WLAN_EID_HT_CAPABILITY, (u8 *)settings->beacon.tail, - settings->beacon.tail_len, 2, enforce_ht_cap1); - slsi_modify_ies(dev, WLAN_EID_HT_CAPABILITY, (u8 *)settings->beacon.tail, - settings->beacon.tail_len, 3, enforce_ht_cap2); - } - } else if (cfg80211_chandef_valid(ndev_vif->chandef)) { - u8 *ht_operation_ie; - u8 sec_chan_offset = 0; - u8 ch; - u8 bw_40_minus_channels[] = { 40, 48, 153, 161, 5, 6, 7, 8, 9, 10, 11 }; - - ht_operation_ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_OPERATION, settings->beacon.tail, - settings->beacon.tail_len); - if (!ht_operation_ie) { - SLSI_NET_ERR(dev, "HT Operation IE is not passed by wpa_supplicant"); - r = -EINVAL; - goto exit_with_vif_mutex; - } - - sec_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - for (ch = 0; ch < ARRAY_SIZE(bw_40_minus_channels); ch++) - if (bw_40_minus_channels[ch] == ndev_vif->chandef->chan->hw_value) { - sec_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - break; - } - - /* Change HT Information IE subset 1 */ - ht_operation_ie += 3; - *(ht_operation_ie) |= sec_chan_offset; - *(ht_operation_ie) |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; - - /* For 80MHz, Enable HT Capabilities : Support 40MHz Channel Width, SGI20 and SGI40 - * for AP (both softAp as well as P2P GO), if firmware supports. - */ - if (cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, settings->beacon.tail, - settings->beacon.tail_len)) { - u8 enforce_ht_cap1 = sdev->fw_ht_cap[0] & (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_LDPC_CODING); - u8 enforce_ht_cap2 = sdev->fw_ht_cap[1] & (IEEE80211_HT_CAP_RX_STBC >> 8); - - slsi_modify_ies(dev, WLAN_EID_HT_CAPABILITY, (u8 *)settings->beacon.tail, - settings->beacon.tail_len, 2, enforce_ht_cap1); - slsi_modify_ies(dev, WLAN_EID_HT_CAPABILITY, (u8 *)settings->beacon.tail, - settings->beacon.tail_len, 3, enforce_ht_cap2); - } - } -#endif - - if (indoor_channel == 1 -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - || (wifi_sharing_channel_switched == 1) -#endif - ) { - slsi_modify_ies_on_channel_switch(dev, settings, ds_params_ie, ht_operation_ie, mgmt, beacon_ie_head_len); - } - ndev_vif->vif_type = FAPI_VIFTYPE_AP; - - if (slsi_mlme_add_vif(sdev, dev, dev->dev_addr, device_address) != 0) { - SLSI_NET_ERR(dev, "slsi_mlme_add_vif failed\n"); - r = -EINVAL; - goto exit_with_vif_mutex; - } - - if (slsi_vif_activated(sdev, dev) != 0) { - SLSI_NET_ERR(dev, "slsi_vif_activated failed\n"); - goto exit_with_vif; - } - - /* Extract the WMM and WPA IEs from settings->beacon.tail - This is sent in add_info_elements and shouldn't be included in start_req - * Cache IEs to be used in later add_info_elements_req. The IEs would be freed during AP stop - */ - wpa_ie_pos = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, settings->beacon.tail, settings->beacon.tail_len); - if (wpa_ie_pos) { - wpa_ie_len = (size_t)(*(wpa_ie_pos + 1) + 2); /* For 0xdd (1) and Tag Length (1) */ - SLSI_NET_DBG2(dev, SLSI_CFG80211, "WPA IE found: Length = %zu\n", wpa_ie_len); - SLSI_EC_GOTO(slsi_cache_ies(wpa_ie_pos, wpa_ie_len, &ndev_vif->ap.cache_wpa_ie, &ndev_vif->ap.wpa_ie_len), r, exit_with_vif); - } - - wmm_ie_pos = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WMM, settings->beacon.tail, settings->beacon.tail_len); - if (wmm_ie_pos) { - wmm_ie_len = (size_t)(*(wmm_ie_pos + 1) + 2); - SLSI_NET_DBG2(dev, SLSI_CFG80211, "WMM IE found: Length = %zu\n", wmm_ie_len); - SLSI_EC_GOTO(slsi_cache_ies(wmm_ie_pos, wmm_ie_len, &ndev_vif->ap.cache_wmm_ie, &ndev_vif->ap.wmm_ie_len), r, exit_with_vif); - } - - slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - - /* Set Vendor specific IEs (WPA, WMM, WPS, P2P) for Beacon, Probe Response and Association Response - * The Beacon and Assoc Rsp IEs can include Extended Capability (WLAN_EID_EXT_CAPAB) IE when supported. - * Some other IEs (like internetworking, etc) can also come if supported. - * The add_info should include only vendor specific IEs and other IEs should be removed if supported in future. - */ - if ((wmm_ie_pos) || (wpa_ie_pos) || (settings->beacon.beacon_ies_len > 0 && settings->beacon.beacon_ies)) { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Add info elements for beacon\n"); - SLSI_EC_GOTO(slsi_ap_prepare_add_info_ies(ndev_vif, settings->beacon.beacon_ies, settings->beacon.beacon_ies_len), r, exit_with_vif); - SLSI_EC_GOTO(slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_BEACON, ndev_vif->ap.add_info_ies, ndev_vif->ap.add_info_ies_len), r, exit_with_vif); - slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - } - - if ((wmm_ie_pos) || (wpa_ie_pos) || (settings->beacon.proberesp_ies_len > 0 && settings->beacon.proberesp_ies)) { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Add info elements for probe response\n"); - SLSI_EC_GOTO(slsi_ap_prepare_add_info_ies(ndev_vif, settings->beacon.proberesp_ies, settings->beacon.proberesp_ies_len), r, exit_with_vif); - SLSI_EC_GOTO(slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_RESPONSE, ndev_vif->ap.add_info_ies, ndev_vif->ap.add_info_ies_len), r, exit_with_vif); - slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - } - - if ((wmm_ie_pos) || (wpa_ie_pos) || (settings->beacon.assocresp_ies_len > 0 && settings->beacon.assocresp_ies)) { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Add info elements for assoc response\n"); - SLSI_EC_GOTO(slsi_ap_prepare_add_info_ies(ndev_vif, settings->beacon.assocresp_ies, settings->beacon.assocresp_ies_len), r, exit_with_vif); - SLSI_EC_GOTO(slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_ASSOCIATION_RESPONSE, ndev_vif->ap.add_info_ies, ndev_vif->ap.add_info_ies_len), r, exit_with_vif); - slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - } - - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO) { - u32 af_bmap_active = SLSI_ACTION_FRAME_PUBLIC; - u32 af_bmap_suspended = SLSI_ACTION_FRAME_PUBLIC; - - r = slsi_mlme_register_action_frame(sdev, dev, af_bmap_active, af_bmap_suspended); - if (r != 0) { - SLSI_NET_ERR(dev, "slsi_mlme_register_action_frame failed: resultcode = %d\n", r); - goto exit_with_vif; - } - } - - if (append_vht_ies) { - ndev_vif->ap.mode = SLSI_80211_MODE_11AC; - } else if (cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, settings->beacon.tail, settings->beacon.tail_len) && - cfg80211_find_ie(WLAN_EID_HT_OPERATION, settings->beacon.tail, settings->beacon.tail_len)) { - ndev_vif->ap.mode = SLSI_80211_MODE_11N; - } else { - ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, settings->beacon.tail, settings->beacon.tail_len); - if (ie) - ndev_vif->ap.mode = slsi_get_supported_mode(ie); - } - - r = slsi_mlme_start(sdev, dev, dev->dev_addr, settings, wpa_ie_pos, wmm_ie_pos, append_vht_ies); - - if ((indoor_channel == 1) -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - || (wifi_sharing_channel_switched == 1) -#endif -#ifdef CONFIG_SCSC_WLAN_ACS_ENABLE - || (sdev->acs_channel_switched == true) -#endif - ) - cfg80211_ch_switch_notify(dev, &settings->chandef); - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (r == 0) - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Soft Ap started on frequency: %d\n", - settings->chandef.chan->center_freq); - if (SLSI_IS_VIF_INDEX_MHS(sdev, ndev_vif)) - ndev_vif->chan = settings->chandef.chan; -#endif - if (r != 0) { - SLSI_NET_ERR(dev, "Start ap failed: resultcode = %d frequency = %d\n", r, - settings->chandef.chan->center_freq); - goto exit_with_vif; - } else if (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO) { - SLSI_P2P_STATE_CHANGE(sdev, P2P_GROUP_FORMED_GO); - } -#ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS - if (ndev_vif->iftype == NL80211_IFTYPE_AP) { - /* Don't care results. */ - slsi_set_num_antennas(dev, 1 /*SISO*/); - } -#endif - ndev_vif->ap.beacon_interval = settings->beacon_interval; - ndev_vif->ap.ssid_len = settings->ssid_len; - memcpy(ndev_vif->ap.ssid, settings->ssid, settings->ssid_len); - - netif_carrier_on(dev); - - if (ndev_vif->ipaddress != cpu_to_be32(0)) - /* Static IP is assigned already */ - slsi_ip_address_changed(sdev, dev, ndev_vif->ipaddress); - - r = slsi_read_disconnect_ind_timeout(sdev, SLSI_PSID_UNIFI_DISCONNECT_TIMEOUT); - if (r != 0) - sdev->device_config.ap_disconnect_ind_timeout = *sdev->sig_wait_cfm_timeout; - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "slsi_read_disconnect_ind_timeout: timeout = %d", sdev->device_config.ap_disconnect_ind_timeout); - goto exit_with_vif_mutex; -exit_with_vif: - slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - slsi_mlme_del_vif(sdev, dev); - slsi_vif_deactivated(sdev, dev); - r = -EINVAL; -exit_with_vif_mutex: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit_with_start_stop_mutex: - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); - return r; -} - -int slsi_change_beacon(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_beacon_data *info) -{ - SLSI_UNUSED_PARAMETER(info); - - return -EOPNOTSUPP; -} - -int slsi_stop_ap(struct wiphy *wiphy, struct net_device *dev) -{ - slsi_reset_throughput_stats(dev); - - return 0; -} - -static int slsi_p2p_group_mgmt_tx(const struct ieee80211_mgmt *mgmt, struct wiphy *wiphy, - struct net_device *dev, struct ieee80211_channel *chan, - unsigned int wait, const u8 *buf, size_t len, - bool dont_wait_for_ack, u64 *cookie) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif; - struct net_device *netdev; - int subtype = slsi_p2p_get_public_action_subtype(mgmt); - int r = 0; - u32 host_tag = slsi_tx_mgmt_host_tag(sdev); - u16 freq = 0; - u32 dwell_time = SLSI_FORCE_SCHD_ACT_FRAME_MSEC; - u16 data_unit_desc = FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME; - - if (sdev->p2p_group_exp_frame != SLSI_P2P_PA_INVALID) { - SLSI_NET_ERR(dev, "sdev->p2p_group_exp_frame : %d\n", sdev->p2p_group_exp_frame); - return -EINVAL; - } - netdev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN); - ndev_vif = netdev_priv(netdev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Sending Action frame (%s) on p2p group vif (%d), vif_index = %d," - "vif_type = %d, chan->hw_value = %d, ndev_vif->chan->hw_value = %d, wait = %d," - "sdev->p2p_group_exp_frame = %d\n", slsi_p2p_pa_subtype_text(subtype), ndev_vif->activated, - ndev_vif->ifnum, ndev_vif->vif_type, chan->hw_value, ndev_vif->chan->hw_value, wait, - ndev_vif->chan->hw_value); - - if (!((ndev_vif->iftype == NL80211_IFTYPE_P2P_GO) || (ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT))) - goto exit_with_error; - - if (chan->hw_value != ndev_vif->chan->hw_value) { - freq = SLSI_FREQ_HOST_TO_FW(chan->center_freq); - dwell_time = wait; - } - - /* Incase of GO dont wait for resp/cfm packets for go-negotiation.*/ - if (subtype != SLSI_P2P_PA_GO_NEG_RSP) - sdev->p2p_group_exp_frame = slsi_p2p_get_exp_peer_frame_subtype(subtype); - - r = slsi_mlme_send_frame_mgmt(sdev, netdev, buf, len, data_unit_desc, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, freq, dwell_time * 1000, 0); - if (r) - goto exit_with_lock; - slsi_assign_cookie_id(cookie, &ndev_vif->mgmt_tx_cookie); - r = slsi_set_mgmt_tx_data(ndev_vif, *cookie, host_tag, buf, len); /* If error then it is returned in exit */ - goto exit_with_lock; - -exit_with_error: - r = -EINVAL; -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -/* Handle mgmt_tx callback for P2P modes */ -static int slsi_p2p_mgmt_tx(const struct ieee80211_mgmt *mgmt, struct wiphy *wiphy, - struct net_device *dev, struct netdev_vif *ndev_vif, - struct ieee80211_channel *chan, unsigned int wait, - const u8 *buf, size_t len, bool dont_wait_for_ack, u64 *cookie) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - - if (ieee80211_is_action(mgmt->frame_control)) { - u16 host_tag = slsi_tx_mgmt_host_tag(sdev); - int subtype = slsi_p2p_get_public_action_subtype(mgmt); - u8 exp_peer_frame; - u32 dwell_time = 0; - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Action frame (%s), unsync_vif_active (%d)\n", slsi_p2p_pa_subtype_text(subtype), ndev_vif->activated); - - if (subtype == SLSI_P2P_PA_INVALID) { - SLSI_NET_ERR(dev, "Invalid Action frame subtype\n"); - goto exit_with_error; - } - - /* Check if unsync vif is available */ - if (sdev->p2p_state == P2P_IDLE_NO_VIF) - if (slsi_p2p_vif_activate(sdev, dev, chan, wait, false) != 0) - goto exit_with_error; - - /* Clear Probe Response IEs if vif was already present with a different channel */ - if (ndev_vif->driver_channel != chan->hw_value) { - if (slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_RESPONSE, NULL, 0) != 0) - SLSI_NET_ERR(dev, "Clearing Probe Response IEs failed for unsync vif\n"); - slsi_unsync_vif_set_probe_rsp_ie(ndev_vif, NULL, 0); - - if (slsi_mlme_set_channel(sdev, dev, chan, SLSI_FW_CHANNEL_DURATION_UNSPECIFIED, 0, 0) != 0) - goto exit_with_vif; - else { - ndev_vif->chan = chan; - ndev_vif->driver_channel = chan->hw_value; - } - } - - /* Check if peer frame response is expected */ - exp_peer_frame = slsi_p2p_get_exp_peer_frame_subtype(subtype); - - if (exp_peer_frame != SLSI_P2P_PA_INVALID) { - if ((subtype == SLSI_P2P_PA_GO_NEG_RSP) && (slsi_p2p_get_go_neg_rsp_status(dev, mgmt) != SLSI_P2P_STATUS_CODE_SUCCESS)) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "GO_NEG_RSP Tx, peer response not expected\n"); - exp_peer_frame = SLSI_P2P_PA_INVALID; - } else { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Peer response expected with action frame (%s)\n", - slsi_p2p_pa_subtype_text(exp_peer_frame)); - - if (ndev_vif->mgmt_tx_data.exp_frame != SLSI_P2P_PA_INVALID) - (void)slsi_set_mgmt_tx_data(ndev_vif, 0, 0, NULL, 0); - - /* Change Force Schedule Duration as peer response is expected */ - if (wait) - dwell_time = wait; - else - dwell_time = SLSI_FORCE_SCHD_ACT_FRAME_MSEC; - } - } - - slsi_assign_cookie_id(cookie, &ndev_vif->mgmt_tx_cookie); - - /* Send the action frame, transmission status indication would be received later */ - if (slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, 0, dwell_time * 1000, 0) != 0) - goto exit_with_vif; - if (subtype == SLSI_P2P_PA_GO_NEG_CFM) - ndev_vif->drv_in_p2p_procedure = false; - else if ((subtype == SLSI_P2P_PA_GO_NEG_REQ) || (subtype == SLSI_P2P_PA_PROV_DISC_REQ)) - ndev_vif->drv_in_p2p_procedure = true; - /* If multiple frames are requested for tx, only the info of first frame would be stored */ - if (ndev_vif->mgmt_tx_data.host_tag == 0) { - unsigned int n_wait = 0; - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Store mgmt frame tx data for cookie = 0x%llx\n", *cookie); - - ret = slsi_set_mgmt_tx_data(ndev_vif, *cookie, host_tag, buf, len); - if (ret != 0) - goto exit_with_vif; - ndev_vif->mgmt_tx_data.exp_frame = exp_peer_frame; - - SLSI_P2P_STATE_CHANGE(sdev, P2P_ACTION_FRAME_TX_RX); - if ((exp_peer_frame == SLSI_P2P_PA_GO_NEG_RSP) || (exp_peer_frame == SLSI_P2P_PA_GO_NEG_CFM)) - /* Retain vif for larger duration that wpa_supplicant asks to wait, - * during GO-Negotiation to allow peer to retry GO neg in bad radio condition. - * Some of phones retry GO-Negotiation after 2 seconds - */ - n_wait = SLSI_P2P_NEG_PROC_UNSYNC_VIF_RETAIN_DURATION; - else if (exp_peer_frame != SLSI_P2P_PA_INVALID) - /* If a peer response is expected queue work to retain vif till wait time else the work will be handled in mgmt_tx_cancel_wait */ - n_wait = wait + SLSI_P2P_MGMT_TX_EXTRA_MSEC; - if (n_wait) { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "retain unsync vif for duration (%d) msec\n", n_wait); - slsi_p2p_queue_unsync_vif_del_work(ndev_vif, n_wait); - } - } else { - /* Already a frame Tx is in progress, send immediate tx_status as success. Sending immediate tx status should be ok - * as supplicant is in another procedure and so these frames would be mostly only response frames. - */ - WARN_ON(sdev->p2p_state != P2P_ACTION_FRAME_TX_RX); - - if (!dont_wait_for_ack) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Send immediate tx_status (cookie = 0x%llx)\n", *cookie); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) - cfg80211_mgmt_tx_status(&ndev_vif->wdev, *cookie, buf, len, true, GFP_KERNEL); -#else - cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL); -#endif - } - } - goto exit; - } - - /* Else send failure for unexpected management frame */ - SLSI_NET_ERR(dev, "Drop Tx frame: Unexpected Management frame\n"); - goto exit_with_error; - -exit_with_vif: - if (sdev->p2p_state != P2P_LISTENING) - slsi_p2p_vif_deactivate(sdev, dev, true); -exit_with_error: - ret = -EINVAL; -exit: - return ret; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) -int slsi_mgmt_tx_cancel_wait(struct wiphy *wiphy, - struct wireless_dev *wdev, - u64 cookie) -{ - struct net_device *dev = wdev->netdev; - -#else -int slsi_mgmt_tx_cancel_wait(struct wiphy *wiphy, - struct net_device *dev, - u64 cookie) -{ -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "iface_num = %d, cookie = 0x%llx, vif_index = %d, vif_type = %d," - "sdev->p2p_state = %d, ndev_vif->mgmt_tx_data.cookie = 0x%llx, sdev->p2p_group_exp_frame = %d," - "sdev->wlan_unsync_vif_state = %d\n", ndev_vif->ifnum, cookie, - ndev_vif->vif_type, sdev->p2p_state, ndev_vif->mgmt_tx_data.cookie, - sdev->p2p_group_exp_frame, sdev->wlan_unsync_vif_state); - - /* If device was in frame tx_rx state, clear mgmt tx data and change state */ - if ((sdev->p2p_state == P2P_ACTION_FRAME_TX_RX) && (ndev_vif->mgmt_tx_data.cookie == cookie)) { - if (ndev_vif->mgmt_tx_data.exp_frame != SLSI_P2P_PA_INVALID) - (void)slsi_mlme_reset_dwell_time(sdev, dev); - - (void)slsi_set_mgmt_tx_data(ndev_vif, 0, 0, NULL, 0); - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - - if (delayed_work_pending(&ndev_vif->unsync.roc_expiry_work)) { - SLSI_P2P_STATE_CHANGE(sdev, P2P_LISTENING); - } else { - slsi_p2p_queue_unsync_vif_del_work(ndev_vif, SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC); - SLSI_P2P_STATE_CHANGE(ndev_vif->sdev, P2P_IDLE_VIF_ACTIVE); - } - } else if ((SLSI_IS_P2P_GROUP_STATE(sdev)) && (sdev->p2p_group_exp_frame != SLSI_P2P_PA_INVALID)) { - /* acquire mutex lock if it is not group net dev */ - slsi_clear_offchannel_data(sdev, (!SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif)) ? true : false); - } else if ((sdev->wlan_unsync_vif_state == WLAN_UNSYNC_VIF_TX) && (ndev_vif->mgmt_tx_data.cookie == cookie)) { - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_VIF_ACTIVE; - cancel_delayed_work(&ndev_vif->unsync.hs2_del_vif_work); - queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.hs2_del_vif_work, msecs_to_jiffies(SLSI_HS2_UNSYNC_VIF_EXTRA_MSEC)); - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return 0; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -void slsi_mgmt_frame_register(struct wiphy *wiphy, - struct wireless_dev *wdev, - u16 frame_type, bool reg) -{ - struct net_device *dev = wdev->netdev; - -#else -void slsi_mgmt_frame_register(struct wiphy *wiphy, - struct net_device *dev, - u16 frame_type, bool reg) -{ -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) */ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - SLSI_UNUSED_PARAMETER(frame_type); - SLSI_UNUSED_PARAMETER(reg); -#endif - - if (WARN_ON(!dev)) - return; - - SLSI_UNUSED_PARAMETER(sdev); -} - -static int slsi_wlan_mgmt_tx(struct slsi_dev *sdev, struct net_device *dev, - struct ieee80211_channel *chan, unsigned int wait, - const u8 *buf, size_t len, bool dont_wait_for_ack, u64 *cookie) -{ - u32 host_tag = slsi_tx_mgmt_host_tag(sdev); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; - - if (!ieee80211_is_auth(mgmt->frame_control)) - slsi_wlan_dump_public_action_subtype(sdev, mgmt, true); - if (!ndev_vif->activated) { - r = slsi_wlan_unsync_vif_activate(sdev, dev, chan, wait); - if (r) - return r; - - r = slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, 0, wait * 1000, 0); - if (r) - goto exit_with_vif; - - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_VIF_TX; - queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.hs2_del_vif_work, msecs_to_jiffies(wait)); - } else { - /* vif is active*/ - if (ieee80211_is_auth(mgmt->frame_control)) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Transmit on the current frequency\n"); - r = slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, - FAPI_MESSAGETYPE_IEEE80211_MGMT, host_tag, 0, wait * 1000, 0); - if (r) - return r; - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_UNSYNCHRONISED) { - cancel_delayed_work(&ndev_vif->unsync.hs2_del_vif_work); - /*even if we fail to cancel the delayed work, we shall go ahead and send action frames*/ - if (ndev_vif->driver_channel != chan->hw_value) { - r = slsi_mlme_set_channel(sdev, dev, chan, SLSI_FW_CHANNEL_DURATION_UNSPECIFIED, 0, 0); - if (r) - goto exit_with_vif; - else { - ndev_vif->driver_channel = chan->hw_value; - } - } - SLSI_NET_DBG1(dev, SLSI_CFG80211, "HS2 vif is active ,send GAS (ANQP) request on channel freq = %d\n", chan->center_freq); - r = slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, 0, wait * 1000, 0); - if (r) - goto exit_with_vif; - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_VIF_TX; - queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.hs2_del_vif_work, msecs_to_jiffies(wait)); - } else if (ndev_vif->chan->hw_value == chan->hw_value) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "STA VIF is active on same channel, send GAS (ANQP) request on channel freq %d\n", chan->center_freq); - r = slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, 0, wait * 1000, 0); - if (r) - return r; - } else { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "STA VIF is active on a different channel, send GAS (ANQP) request on channel freq %d\n", chan->center_freq); - r = slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, SLSI_FREQ_HOST_TO_FW(chan->center_freq), wait * 1000, 0); - if (r) - return r; - } - } - - slsi_assign_cookie_id(cookie, &ndev_vif->mgmt_tx_cookie); - slsi_set_mgmt_tx_data(ndev_vif, *cookie, host_tag, buf, len); - return r; - -exit_with_vif: - slsi_wlan_unsync_vif_deactivate(sdev, dev, true); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -int slsi_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_mgmt_tx_params *params, - u64 *cookie) -{ -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) -int slsi_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, bool no_cck, bool dont_wait_for_ack, u64 *cookie) -{ - struct net_device *dev = wdev->netdev; - -#else -int slsi_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, bool offchan, - enum nl80211_channel_type channel_type, - bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, bool no_cck, - bool dont_wait_for_ack, u64 *cookie) -{ -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */ - - /* Note to explore for AP ::All public action frames which come to host should be handled properly - * Additionally, if PMF is negotiated over the link, the host shall not issue "mlme-send-frame.request" - * primitive for action frames before the pairwise keys have been installed in F/W. Presently, for - * SoftAP with PMF support, there is no scenario in which slsi_mlme_send_frame will be called for - * action frames for VIF TYPE = AP. - */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) - struct net_device *dev = wdev->netdev; - struct ieee80211_channel *chan = params->chan; - bool offchan = params->offchan; - unsigned int wait = params->wait; - const u8 *buf = params->buf; - size_t len = params->len; - bool no_cck = params->no_cck; - bool dont_wait_for_ack = params->dont_wait_for_ack; -#endif - - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *)buf; - int r = 0; - - SLSI_UNUSED_PARAMETER(offchan); - SLSI_UNUSED_PARAMETER(no_cck); - SLSI_MUTEX_LOCK(sdev->start_stop_mutex); - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { - SLSI_WARN(sdev, "device not started yet (device_state:%d)\n", sdev->device_state); - r = -EINVAL; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!(ieee80211_is_auth(mgmt->frame_control))) { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Mgmt Frame Tx: iface_num = %d, channel = %d, wait = %d, noAck = %d," - "offchannel = %d, mgmt->frame_control = %d, vif_type = %d\n", ndev_vif->ifnum, chan->hw_value, - wait, dont_wait_for_ack, offchan, mgmt->frame_control, ndev_vif->vif_type); - } else { - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Received Auth Frame"); - } - - if (!(ieee80211_is_mgmt(mgmt->frame_control))) { - SLSI_NET_ERR(dev, "Drop Tx frame: Not a Management frame\n"); - r = -EINVAL; - goto exit; - } - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif) || (ndev_vif->iftype == NL80211_IFTYPE_AP && (ieee80211_is_auth(mgmt->frame_control)))) { - r = slsi_wlan_mgmt_tx(SDEV_FROM_WIPHY(wiphy), dev, chan, wait, buf, len, dont_wait_for_ack, cookie); - goto exit; - } - - /*P2P*/ - - /* Drop Probe Responses which can come in P2P Device and P2P Group role */ - if (ieee80211_is_probe_resp(mgmt->frame_control)) { - /* Ideally supplicant doesn't expect Tx status for Probe Rsp. Send tx status just in case it requests ack */ - if (!dont_wait_for_ack) { - slsi_assign_cookie_id(cookie, &ndev_vif->mgmt_tx_cookie); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_KERNEL); -#else - cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL); -#endif - } - goto exit; - } - - if (SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - /* Check whether STA scan is running or not. If yes, then abort the STA scan */ - slsi_abort_sta_scan(sdev); - if (SLSI_IS_P2P_GROUP_STATE(sdev)) - r = slsi_p2p_group_mgmt_tx(mgmt, wiphy, dev, chan, wait, buf, len, dont_wait_for_ack, cookie); - else - r = slsi_p2p_mgmt_tx(mgmt, wiphy, dev, ndev_vif, chan, wait, buf, len, dont_wait_for_ack, cookie); - } else if (SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif)) - if (chan->hw_value == ndev_vif->chan->hw_value) { - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - u16 host_tag = slsi_tx_mgmt_host_tag(sdev); - - r = slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, 0, 0, 0); - if (r) { - SLSI_NET_ERR(dev, "Failed to send action frame, r = %d\n", r); - goto exit; - } - slsi_assign_cookie_id(cookie, &ndev_vif->mgmt_tx_cookie); - r = slsi_set_mgmt_tx_data(ndev_vif, *cookie, host_tag, buf, len); - } -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); - return r; -} - -/* cw = (2^n -1). But WMM IE needs value n. */ -u8 slsi_get_ecw(int cw) -{ - int ecw = 0; - - cw = cw + 1; - do { - cw = cw >> 1; - ecw++; - } while (cw); - return ecw - 1; -} - -int slsi_set_txq_params(struct wiphy *wiphy, struct net_device *ndev, - struct ieee80211_txq_params *params) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(ndev); - struct slsi_wmm_parameter_element *wmm_ie = &ndev_vif->ap.wmm_ie; - int r = 0; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) - int ac = params->ac; -#else - int ac = params->queue; -#endif - /* Index remapping for AC from nl80211_ac enum to slsi_ac_index_wmm enum (index to be used in the IE). - * Kernel version less than 3.5.0 doesn't support nl80211_ac enum hence not using the nl80211_ac enum. - * Eg. NL80211_AC_VO (index value 0) would be remapped to AC_VO (index value 3). - * Don't change the order of array elements. - */ - u8 ac_index_map[4] = { AC_VO, AC_VI, AC_BE, AC_BK }; - int ac_remapped = ac_index_map[ac]; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_NET_DBG2(ndev, SLSI_CFG80211, " ac= %x, ac_remapped = %d aifs = %d, cmin=%x cmax = %x, txop = %x," - "vif_index = %d vif_type = %d", ac, ac_remapped, params->aifs, params->cwmin, params->cwmax, - params->txop, ndev_vif->ifnum, ndev_vif->vif_type); - - if (ndev_vif->activated) { - wmm_ie->ac[ac_remapped].aci_aifsn = (ac_remapped << 5) | (params->aifs & 0x0f); - wmm_ie->ac[ac_remapped].ecw = ((slsi_get_ecw(params->cwmax)) << 4) | ((slsi_get_ecw(params->cwmin)) & 0x0f); - wmm_ie->ac[ac_remapped].txop_limit = cpu_to_le16(params->txop); - if (ac == 3) { - wmm_ie->eid = SLSI_WLAN_EID_VENDOR_SPECIFIC; - wmm_ie->len = 24; - wmm_ie->oui[0] = 0x00; - wmm_ie->oui[1] = 0x50; - wmm_ie->oui[2] = 0xf2; - wmm_ie->oui_type = WLAN_OUI_TYPE_MICROSOFT_WMM; - wmm_ie->oui_subtype = 1; - wmm_ie->version = 1; - wmm_ie->qos_info = 0; - wmm_ie->reserved = 0; - r = slsi_mlme_add_info_elements(sdev, ndev, FAPI_PURPOSE_LOCAL, (const u8 *)wmm_ie, sizeof(struct slsi_wmm_parameter_element)); - if (r) - SLSI_NET_ERR(ndev, "Error sending TX Queue Parameters for AP error = %d", r); - } - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG -int slsi_synchronised_response(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_external_auth_params *params) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - r = slsi_mlme_synchronised_response(sdev, dev, params); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -static int slsi_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) - r = slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_ASSOCIATION_REQUEST, ftie->ie, ftie->ie_len); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -int slsi_set_mac_acl(struct wiphy *wiphy, struct net_device *dev, - const struct cfg80211_acl_data *params) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_SET_ACL.request\n"); - return -EOPNOTSUPP; - } - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (FAPI_VIFTYPE_AP != ndev_vif->vif_type) { - SLSI_NET_ERR(dev, "Invalid vif type: %d\n", ndev_vif->vif_type); - r = -EINVAL; - goto exit; - } - SLSI_NET_DBG2(dev, SLSI_CFG80211, "ACL:: Policy: %d Number of stations: %d\n", params->acl_policy, params->n_acl_entries); - r = slsi_mlme_set_acl(sdev, dev, ndev_vif->ifnum, params); - if (r != 0) - SLSI_NET_ERR(dev, "mlme_set_acl_req returned with CFM failure\n"); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} -#endif - -static struct cfg80211_ops slsi_ops = { - .add_virtual_intf = slsi_add_virtual_intf, - .del_virtual_intf = slsi_del_virtual_intf, - .change_virtual_intf = slsi_change_virtual_intf, - - .scan = slsi_scan, - .connect = slsi_connect, - .disconnect = slsi_disconnect, - - .add_key = slsi_add_key, - .del_key = slsi_del_key, - .get_key = slsi_get_key, - .set_default_key = slsi_set_default_key, - .set_default_mgmt_key = slsi_config_default_mgmt_key, - - .set_wiphy_params = slsi_set_wiphy_params, - - .del_station = slsi_del_station, - .get_station = slsi_get_station, - .set_tx_power = slsi_set_tx_power, - .get_tx_power = slsi_get_tx_power, - .set_power_mgmt = slsi_set_power_mgmt, - - .suspend = slsi_suspend, - .resume = slsi_resume, - - .set_pmksa = slsi_set_pmksa, - .del_pmksa = slsi_del_pmksa, - .flush_pmksa = slsi_flush_pmksa, - - .remain_on_channel = slsi_remain_on_channel, - .cancel_remain_on_channel = slsi_cancel_remain_on_channel, - - .change_bss = slsi_change_bss, -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 5, 0)) - .set_channel = slsi_set_channel, -#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 5, 0)) */ - - .start_ap = slsi_start_ap, - .change_beacon = slsi_change_beacon, - .stop_ap = slsi_stop_ap, - - .sched_scan_start = slsi_sched_scan_start, - .sched_scan_stop = slsi_sched_scan_stop, - - .mgmt_frame_register = slsi_mgmt_frame_register, - .mgmt_tx = slsi_mgmt_tx, - .mgmt_tx_cancel_wait = slsi_mgmt_tx_cancel_wait, - .set_txq_params = slsi_set_txq_params, -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG - .external_auth = slsi_synchronised_response, -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - .set_mac_acl = slsi_set_mac_acl, - .update_ft_ies = slsi_update_ft_ies, -#endif - .tdls_oper = slsi_tdls_oper, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) -#ifdef CONFIG_SCSC_WLAN_DEBUG - .set_monitor_channel = slsi_set_monitor_channel, -#endif - .set_qos_map = slsi_set_qos_map -#endif -}; - -#define RATE_LEGACY(_rate, _hw_value, _flags) { \ - .bitrate = (_rate), \ - .hw_value = (_hw_value), \ - .flags = (_flags), \ -} - -#define CHAN2G(_freq, _idx) { \ - .band = NL80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 17, \ -} - -#define CHAN5G(_freq, _idx) { \ - .band = NL80211_BAND_5GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 17, \ -} - -static struct ieee80211_channel slsi_2ghz_channels[] = { - CHAN2G(2412, 1), - CHAN2G(2417, 2), - CHAN2G(2422, 3), - CHAN2G(2427, 4), - CHAN2G(2432, 5), - CHAN2G(2437, 6), - CHAN2G(2442, 7), - CHAN2G(2447, 8), - CHAN2G(2452, 9), - CHAN2G(2457, 10), - CHAN2G(2462, 11), - CHAN2G(2467, 12), - CHAN2G(2472, 13), - CHAN2G(2484, 14), -}; - -static struct ieee80211_rate slsi_11g_rates[] = { - RATE_LEGACY(10, 1, 0), - RATE_LEGACY(20, 2, IEEE80211_RATE_SHORT_PREAMBLE), - RATE_LEGACY(55, 3, IEEE80211_RATE_SHORT_PREAMBLE), - RATE_LEGACY(110, 6, IEEE80211_RATE_SHORT_PREAMBLE), - RATE_LEGACY(60, 4, 0), - RATE_LEGACY(90, 5, 0), - RATE_LEGACY(120, 7, 0), - RATE_LEGACY(180, 8, 0), - RATE_LEGACY(240, 9, 0), - RATE_LEGACY(360, 10, 0), - RATE_LEGACY(480, 11, 0), - RATE_LEGACY(540, 12, 0), -}; - -static struct ieee80211_channel slsi_5ghz_channels[] = { - /* _We_ call this UNII 1 */ - CHAN5G(5180, 36), - CHAN5G(5200, 40), - CHAN5G(5220, 44), - CHAN5G(5240, 48), - /* UNII 2 */ - CHAN5G(5260, 52), - CHAN5G(5280, 56), - CHAN5G(5300, 60), - CHAN5G(5320, 64), - /* "Middle band" */ - CHAN5G(5500, 100), - CHAN5G(5520, 104), - CHAN5G(5540, 108), - CHAN5G(5560, 112), - CHAN5G(5580, 116), - CHAN5G(5600, 120), - CHAN5G(5620, 124), - CHAN5G(5640, 128), - CHAN5G(5660, 132), - CHAN5G(5680, 136), - CHAN5G(5700, 140), - CHAN5G(5720, 144), - /* UNII 3 */ - CHAN5G(5745, 149), - CHAN5G(5765, 153), - CHAN5G(5785, 157), - CHAN5G(5805, 161), - CHAN5G(5825, 165), -}; - -/* note fw_rate_idx_to_host_11a_idx[] below must change if this table changes */ - -static struct ieee80211_rate wifi_11a_rates[] = { - RATE_LEGACY(60, 4, 0), - RATE_LEGACY(90, 5, 0), - RATE_LEGACY(120, 7, 0), - RATE_LEGACY(180, 8, 0), - RATE_LEGACY(240, 9, 0), - RATE_LEGACY(360, 10, 0), - RATE_LEGACY(480, 11, 0), - RATE_LEGACY(540, 12, 0), -}; - -static struct ieee80211_sta_ht_cap slsi_ht_cap = { - .ht_supported = true, - .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_RX_STBC | - IEEE80211_HT_CAP_GRN_FLD | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_4, - .mcs = { - .rx_mask = { 0xff, 0, }, - .rx_highest = cpu_to_le16(0), - .tx_params = 0, - }, -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -struct ieee80211_sta_vht_cap slsi_vht_cap = { - .vht_supported = true, - .cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | - IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_RXSTBC_1 | - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | - (5 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT), - .vht_mcs = { - .rx_mcs_map = cpu_to_le16(0xfffe), - .rx_highest = cpu_to_le16(0), - .tx_mcs_map = cpu_to_le16(0xfffe), - .tx_highest = cpu_to_le16(0), - }, -}; -#endif - -struct ieee80211_supported_band slsi_band_2ghz = { - .channels = slsi_2ghz_channels, - .band = NL80211_BAND_2GHZ, - .n_channels = ARRAY_SIZE(slsi_2ghz_channels), - .bitrates = slsi_11g_rates, - .n_bitrates = ARRAY_SIZE(slsi_11g_rates), -}; - -struct ieee80211_supported_band slsi_band_5ghz = { - .channels = slsi_5ghz_channels, - .band = NL80211_BAND_5GHZ, - .n_channels = ARRAY_SIZE(slsi_5ghz_channels), - .bitrates = wifi_11a_rates, - .n_bitrates = ARRAY_SIZE(wifi_11a_rates), -}; - -static const u32 slsi_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, - WLAN_CIPHER_SUITE_AES_CMAC, - WLAN_CIPHER_SUITE_SMS4, - WLAN_CIPHER_SUITE_PMK, - WLAN_CIPHER_SUITE_GCMP, - WLAN_CIPHER_SUITE_GCMP_256, - WLAN_CIPHER_SUITE_CCMP_256, - WLAN_CIPHER_SUITE_BIP_GMAC_128, - WLAN_CIPHER_SUITE_BIP_GMAC_256 -}; - -static const struct ieee80211_txrx_stypes - ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_AP] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) - }, - [NL80211_IFTYPE_STATION] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) - }, -}; - -/* Interface combinations supported by driver */ -static struct ieee80211_iface_limit iface_limits[] = { -#ifdef CONFIG_SCSC_WLAN_STA_ONLY - /* Basic STA-only */ - { - .max = CONFIG_SCSC_WLAN_MAX_INTERFACES, - .types = BIT(NL80211_IFTYPE_STATION), - }, -#else - /* AP mode: # AP <= 1 on channel = 1 */ - { - .max = 1, - .types = BIT(NL80211_IFTYPE_AP), - }, - /* STA and P2P mode: #STA <= 1, #{P2P-client,P2P-GO} <= 1 on two channels */ - /* For P2P, the device mode and group mode is first started as STATION and then changed. - * Similarly it is changed to STATION on group removal. Hence set maximum interfaces for STATION. - */ - { - .max = CONFIG_SCSC_WLAN_MAX_INTERFACES, - .types = BIT(NL80211_IFTYPE_STATION), - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO), - }, - /* ADHOC mode: #ADHOC <= 1 on channel = 1 */ - { - .max = 1, - .types = BIT(NL80211_IFTYPE_ADHOC), - }, -#endif -}; - -static struct ieee80211_regdomain slsi_regdomain = { - .reg_rules = { - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - REG_RULE(0, 0, 0, 0, 0, 0), - } -}; - -static struct ieee80211_iface_combination iface_comb[] = { - { - .limits = iface_limits, - .n_limits = ARRAY_SIZE(iface_limits), - .num_different_channels = 2, - .max_interfaces = CONFIG_SCSC_WLAN_MAX_INTERFACES, - }, -}; - -#ifdef CONFIG_PM -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) -static struct cfg80211_wowlan slsi_wowlan_config = { - .any = true, -}; -#endif -#endif - -struct slsi_dev *slsi_cfg80211_new(struct device *dev) -{ - struct wiphy *wiphy; - struct slsi_dev *sdev = NULL; - - SLSI_DBG1_NODEV(SLSI_CFG80211, "wiphy_new()\n"); - wiphy = wiphy_new(&slsi_ops, sizeof(struct slsi_dev)); - if (!wiphy) { - SLSI_ERR_NODEV("wiphy_new() failed"); - return NULL; - } - - sdev = (struct slsi_dev *)wiphy->priv; - - sdev->wiphy = wiphy; - - set_wiphy_dev(wiphy, dev); - - /* Allow changing of the netns, if NOT set then no changes are allowed */ - wiphy->flags |= WIPHY_FLAG_NETNS_OK; - wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; - wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; - - /* wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; - * - * Whilst the firmware does support roaming the driver MUST NOT advertise it - * as the supplicant will NOT send the BSSID and frequency information in the - * connect cfg80211 op. - * If the driver advertises FW_ROAM then the supplicant expects it to perform - * any scans required to find an appropriate AP and will only pass the SSID - */ - - wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | - WIPHY_FLAG_AP_UAPSD; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - wiphy->max_acl_mac_addrs = SLSI_AP_PEER_CONNECTIONS_MAX; -#endif - - wiphy->privid = sdev; - - wiphy->interface_modes = -#ifdef CONFIG_SCSC_WLAN_STA_ONLY - BIT(NL80211_IFTYPE_STATION); -#else - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_SCSC_WLAN_DEBUG - BIT(NL80211_IFTYPE_MONITOR) | -#endif - BIT(NL80211_IFTYPE_ADHOC); -#endif - slsi_band_2ghz.ht_cap = slsi_ht_cap; - slsi_band_5ghz.ht_cap = slsi_ht_cap; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - slsi_band_5ghz.vht_cap = slsi_vht_cap; -#endif - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - wiphy->bands[NL80211_BAND_2GHZ] = &slsi_band_2ghz; - wiphy->bands[NL80211_BAND_5GHZ] = &slsi_band_5ghz; - - memset(&sdev->device_config, 0, sizeof(struct slsi_dev_config)); - sdev->device_config.band_5G = &slsi_band_5ghz; - sdev->device_config.band_2G = &slsi_band_2ghz; - sdev->device_config.domain_info.regdomain = &slsi_regdomain; - - wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->max_remain_on_channel_duration = 5000; /* 5000 msec */ - - wiphy->cipher_suites = slsi_cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(slsi_cipher_suites); - - wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; - - /* Driver interface combinations */ - wiphy->n_iface_combinations = ARRAY_SIZE(iface_comb); - wiphy->iface_combinations = iface_comb; - - /* Basic scan parameters */ - wiphy->max_scan_ssids = 10; - wiphy->max_scan_ie_len = 2048; - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 0)) - /* Scheduled scanning support */ - wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) - /* Parameters for Scheduled Scanning Support */ - wiphy->max_sched_scan_reqs = 1; - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI); -#endif - - /* Match the maximum number of SSIDs that could be requested from wpa_supplicant */ - wiphy->max_sched_scan_ssids = 16; - - /* To get a list of SSIDs rather than just the wildcard SSID need to support match sets */ - wiphy->max_match_sets = 16; - - wiphy->max_sched_scan_ie_len = 2048; - -#ifdef CONFIG_PM -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) - wiphy->wowlan = NULL; - wiphy->wowlan_config = &slsi_wowlan_config; -#endif -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - wiphy->regulatory_flags |= (REGULATORY_STRICT_REG | - REGULATORY_CUSTOM_REG | - REGULATORY_DISABLE_BEACON_HINTS); -#endif -#ifndef CONFIG_SCSC_WLAN_STA_ONLY - /* P2P flags */ - wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX; - - /* Enable Probe response offloading w.r.t WPS and P2P */ - wiphy->probe_resp_offload |= - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; - - /* TDLS support */ - wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; -#endif - /* Mac Randomization */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; - wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; -#endif -#endif -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG - wiphy->features |= NL80211_FEATURE_SAE; -#endif - return sdev; -} - -int slsi_cfg80211_register(struct slsi_dev *sdev) -{ - SLSI_DBG1(sdev, SLSI_CFG80211, "wiphy_register()\n"); - return wiphy_register(sdev->wiphy); -} - -void slsi_cfg80211_unregister(struct slsi_dev *sdev) -{ -#ifdef CONFIG_PM -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) - sdev->wiphy->wowlan = NULL; - sdev->wiphy->wowlan_config = NULL; -#endif -#endif - SLSI_DBG1(sdev, SLSI_CFG80211, "wiphy_unregister()\n"); - wiphy_unregister(sdev->wiphy); -} - -void slsi_cfg80211_free(struct slsi_dev *sdev) -{ - SLSI_DBG1(sdev, SLSI_CFG80211, "wiphy_free()\n"); - wiphy_free(sdev->wiphy); -} - -void slsi_cfg80211_update_wiphy(struct slsi_dev *sdev) -{ - /* update supported Bands */ - if (sdev->band_5g_supported) { - sdev->wiphy->bands[NL80211_BAND_5GHZ] = &slsi_band_5ghz; - sdev->device_config.band_5G = &slsi_band_5ghz; - } else { - sdev->wiphy->bands[NL80211_BAND_5GHZ] = NULL; - sdev->device_config.band_5G = NULL; - } - - /* update HT features */ - if (sdev->fw_ht_enabled) { - slsi_ht_cap.ht_supported = true; - slsi_ht_cap.cap = le16_to_cpu(*(u16 *)sdev->fw_ht_cap); - slsi_ht_cap.ampdu_density = (sdev->fw_ht_cap[2] & IEEE80211_HT_AMPDU_PARM_DENSITY) >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT; - slsi_ht_cap.ampdu_factor = sdev->fw_ht_cap[2] & IEEE80211_HT_AMPDU_PARM_FACTOR; - } else { - slsi_ht_cap.ht_supported = false; - } - slsi_band_2ghz.ht_cap = slsi_ht_cap; - slsi_band_5ghz.ht_cap = slsi_ht_cap; - - /* update VHT features */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (sdev->fw_vht_enabled) { - slsi_vht_cap.vht_supported = true; - slsi_vht_cap.cap = le32_to_cpu(*(u32 *)sdev->fw_vht_cap); - } else { - slsi_vht_cap.vht_supported = false; - } - slsi_band_5ghz.vht_cap = slsi_vht_cap; -#endif - - SLSI_INFO(sdev, "BANDS SUPPORTED -> 2.4:'%c' 5:'%c'\n", sdev->wiphy->bands[NL80211_BAND_2GHZ] ? 'Y' : 'N', - sdev->wiphy->bands[NL80211_BAND_5GHZ] ? 'Y' : 'N'); - SLSI_INFO(sdev, "HT/VHT SUPPORTED -> HT:'%c' VHT:'%c'\n", sdev->fw_ht_enabled ? 'Y' : 'N', - sdev->fw_vht_enabled ? 'Y' : 'N'); - SLSI_INFO(sdev, "HT -> cap:0x%04x ampdu_density:%d ampdu_factor:%d\n", slsi_ht_cap.cap, slsi_ht_cap.ampdu_density, slsi_ht_cap.ampdu_factor); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - SLSI_INFO(sdev, "VHT -> cap:0x%08x\n", slsi_vht_cap.cap); -#endif -} diff --git a/drivers/net/wireless/scsc/cfg80211_ops.h b/drivers/net/wireless/scsc/cfg80211_ops.h deleted file mode 100755 index 3e6c6ae4e5bc..000000000000 --- a/drivers/net/wireless/scsc/cfg80211_ops.h +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_CFG80211_OPS_H__ -#define __SLSI_CFG80211_OPS_H__ - -#include - -struct slsi_dev; - -#define SDEV_FROM_WIPHY(wiphy) ((struct slsi_dev *)(wiphy)->priv) -#define WLAN_CIPHER_SUITE_PMK 0x00904C00 - -#define SLSI_WPS_REQUEST_TYPE_POS 15 -#define SLSI_WPS_REQUEST_TYPE_ENROLEE_INFO_ONLY 0x00 -#define SLSI_WPS_OUI_PATTERN 0x04F25000 -#define SLSI_P2P_OUI_PATTERN 0x099a6f50 -#define SLSI_VENDOR_OUI_AND_TYPE_LEN 4 - -struct slsi_dev *slsi_cfg80211_new(struct device *dev); -int slsi_cfg80211_register(struct slsi_dev *sdev); -void slsi_cfg80211_unregister(struct slsi_dev *sdev); -void slsi_cfg80211_free(struct slsi_dev *sdev); -void slsi_cfg80211_update_wiphy(struct slsi_dev *sdev); -#endif /*__SLSI_CFG80211_OPS_H__*/ diff --git a/drivers/net/wireless/scsc/cm_if.c b/drivers/net/wireless/scsc/cm_if.c deleted file mode 100755 index 38c8dc46c817..000000000000 --- a/drivers/net/wireless/scsc/cm_if.c +++ /dev/null @@ -1,716 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - * Chip Manager interface - * - ****************************************************************************/ - -#include "mgt.h" -#include "dev.h" -#include "debug.h" -#include "scsc_wifi_cm_if.h" -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING -#include "hip4_sampler.h" -#endif - -#include -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif - -static bool EnableTestMode; -module_param(EnableTestMode, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(EnableTestMode, "Enable WlanLite test mode driver."); - -static BLOCKING_NOTIFIER_HEAD(slsi_wlan_notifier); - -static bool EnableRfTestMode; -module_param(EnableRfTestMode, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(EnableRfTestMode, "Enable RF test mode driver."); - -static struct mutex slsi_start_mutex; -static int recovery_in_progress; -static u16 latest_scsc_panic_code; - - -/* TODO: Would be good to get this removed - use module_client? */ -struct slsi_cm_ctx { - struct slsi_dev *sdev; -}; - -/* Only one wlan service instance is assumed for now. */ -static struct slsi_cm_ctx cm_ctx; - -static void slsi_hip_block_bh(struct slsi_dev *sdev); - -int slsi_wlan_service_notifier_register(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&slsi_wlan_notifier, nb); -} - -int slsi_wlan_service_notifier_unregister(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&slsi_wlan_notifier, nb); -} - -static int wlan_suspend(struct scsc_service_client *client) -{ - struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client); - - SLSI_INFO_NODEV("Nofity registered functions\n"); - blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_SUSPEND, sdev); - - return 0; -} - -static int wlan_resume(struct scsc_service_client *client) -{ - struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client); - - SLSI_INFO_NODEV("Nofity registered functions\n"); - blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_RESUME, sdev); - - return 0; -} - -static void wlan_stop_on_failure(struct scsc_service_client *client) -{ - int state; - struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client); - - SLSI_INFO_NODEV("\n"); - - mutex_lock(&slsi_start_mutex); - recovery_in_progress = 1; - sdev->recovery_status = 1; - state = atomic_read(&sdev->cm_if.cm_if_state); - if (state != SCSC_WIFI_CM_IF_STATE_STOPPED) { - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_BLOCKED); - sdev->fail_reported = true; - - /* If next state is stopped, then don't signal recovery since - * the Android framework won't/shouldn't restart (supplicant - * stop and start). - */ - if (sdev->recovery_next_state != SCSC_WIFI_CM_IF_STATE_STOPPING) { - slsi_hip_block_bh(sdev); - - /* Stop wlan operations. Send event to registered parties */ - mutex_unlock(&slsi_start_mutex); - SLSI_INFO_NODEV("Nofity registered functions\n"); - blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_STOP, sdev); - mutex_lock(&slsi_start_mutex); - } - } else { - SLSI_INFO_NODEV("Wi-Fi service driver not started\n"); - } - - mutex_unlock(&slsi_start_mutex); -} - -static void wlan_failure_reset(struct scsc_service_client *client, u16 scsc_panic_code) -{ - SLSI_INFO_NODEV("\n"); - latest_scsc_panic_code = scsc_panic_code; -} - -int slsi_check_rf_test_mode(void) -{ - struct file *fp = NULL; -#if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000 - char *filepath = "/data/vendor/conn/.psm.info"; -#else - char *filepath = "/data/misc/conn/.psm.info"; -#endif - char power_val = 0; - - fp = filp_open(filepath, O_RDONLY, 0); - if (IS_ERR(fp) || (!fp)) { - pr_err("%s is not exist.\n", filepath); - return -ENOENT; /* -2 */ - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - kernel_read(fp, &power_val, 1, &fp->f_pos); -#else - kernel_read(fp, fp->f_pos, &power_val, 1); -#endif - /* if power_val is 0, it means rf_test mode by rf. */ - if (power_val == '0') { - pr_err("*#rf# is enabled.\n"); - EnableRfTestMode = 1; - } else { - pr_err("*#rf# is disabled.\n"); - EnableRfTestMode = 0; - } - - if (fp) - filp_close(fp, NULL); - - return 0; -} - -/* WLAN service driver registration - * ================================ - */ -void slsi_wlan_service_probe(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - struct slsi_dev *sdev; - struct device *dev; - struct scsc_service_client mx_wlan_client; -#ifdef CONFIG_SCSC_LOG_COLLECTION - char buf[SCSC_LOG_FAPI_VERSION_SIZE]; -#endif - - SLSI_UNUSED_PARAMETER(module_client); - - SLSI_INFO_NODEV("WLAN service probe\n"); - - mutex_lock(&slsi_start_mutex); - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery_in_progress) - goto done; - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY) { - SLSI_INFO_NODEV("Probe recovery\n"); - sdev = cm_ctx.sdev; - recovery_in_progress = 0; - sdev->fail_reported = false; - sdev->recovery_status = 0; - sdev->mlme_blocked = false; - complete_all(&sdev->recovery_completed); - } else { - /* Register callbacks */ - mx_wlan_client.stop_on_failure = wlan_stop_on_failure; - mx_wlan_client.failure_reset = wlan_failure_reset; - mx_wlan_client.suspend = wlan_suspend; - mx_wlan_client.resume = wlan_resume; - - dev = scsc_service_get_device_by_mx(mx); - - /* The mutex must be released at this point since the attach - * process may call various functions including - * slsi_sm_wlan_service_start and slsi_sm_wlan_service_open, which will - * claim the same mutex. - */ - mutex_unlock(&slsi_start_mutex); - sdev = slsi_dev_attach(dev, mx, &mx_wlan_client); - mutex_lock(&slsi_start_mutex); - if (!sdev) { - SLSI_ERR_NODEV("WLAN attach failed - slsi_dev_attach\n"); - goto done; - } - - cm_ctx.sdev = sdev; /* TODO: For now. */ - - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_PROBING); - get_device(dev); - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - hip4_sampler_create(sdev, mx); -#endif -#ifdef CONFIG_SCSC_LOG_COLLECTION - memset(buf, 0, SCSC_LOG_FAPI_VERSION_SIZE); - /* Write FAPI VERSION to collector header */ - /* IMPORTANT - Do not change the formatting as User space tooling is parsing the string - * to read SAP fapi versions. - */ - snprintf(buf, SCSC_LOG_FAPI_VERSION_SIZE, "ma:%u.%u, mlme:%u.%u, debug:%u.%u, test:%u.%u", - FAPI_MAJOR_VERSION(FAPI_DATA_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_DATA_SAP_VERSION), - FAPI_MAJOR_VERSION(FAPI_CONTROL_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_CONTROL_SAP_VERSION), - FAPI_MAJOR_VERSION(FAPI_DEBUG_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_DEBUG_SAP_VERSION), - FAPI_MAJOR_VERSION(FAPI_TEST_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_TEST_SAP_VERSION)); - - scsc_log_collector_write_fapi(buf, SCSC_LOG_FAPI_VERSION_SIZE); -#endif - } - - if (reason != SCSC_MODULE_CLIENT_REASON_RECOVERY) - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_PROBED); - -done: - mutex_unlock(&slsi_start_mutex); -} - -/* service_clean_up_locked expects the slsi_start_mutex mutex to be claimed when - * service_clean_up_locked is called. - */ -static void service_clean_up_locked(struct slsi_dev *sdev) -{ - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_REMOVING); - put_device(sdev->dev); - - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_REMOVED); - - sdev->maxwell_core = NULL; - - /* The mutex must be released at this point since the tear down - * process will call various functions including - * slsi_sm_wlan_service_stop and slsi_sm_wlan_service_close, which will - * claim the same mutex. - */ - mutex_unlock(&slsi_start_mutex); - slsi_dev_detach(sdev); - mutex_lock(&slsi_start_mutex); -} - -static void slsi_wlan_service_remove(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason) -{ - struct slsi_dev *sdev; - int state; - - SLSI_UNUSED_PARAMETER(mx); - SLSI_UNUSED_PARAMETER(module_client); - - sdev = cm_ctx.sdev; - if (!sdev) { - SLSI_INFO_NODEV("no sdev\n"); - return; - } - - if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery_in_progress) { - SLSI_INFO_NODEV("WLAN service remove - recovery. Service not active.\n"); - } else if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && recovery_in_progress) { - int r; - - SLSI_INFO_NODEV("WLAN service remove - recovery\n"); - - /* Only indicate if the next state is not stopping. The recovery - * handling won't have any affect if the framework is closing - * anyway. - */ - if (sdev->recovery_next_state != SCSC_WIFI_CM_IF_STATE_STOPPING) { - SLSI_INFO_NODEV("Nofity registered functions\n"); - blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_FAILURE_RESET, sdev); - } - - mutex_lock(&slsi_start_mutex); - /** - * If there was a request to stop during the recovery, then do - * not sent a hang - just stop here. The Wi-Fi service driver is - * ready to be turned on again. Let the service_stop complete. - */ - complete_all(&sdev->recovery_remove_completion); - if (sdev->recovery_next_state == SCSC_WIFI_CM_IF_STATE_STOPPING) { - SLSI_INFO_NODEV("Recovery - next state stopping\n"); - } else { - SLSI_INFO_NODEV("Calling slsi_send_hanged_vendor_event with latest_scsc_panic_code=0x%x\n", - latest_scsc_panic_code); - if (slsi_send_hanged_vendor_event(sdev, latest_scsc_panic_code) < 0) - SLSI_ERR(sdev, "Failed to send hang event\n"); - - /* Complete any pending ctrl signals, which will prevent - * the hang event from being processed. - */ - complete_all(&sdev->sig_wait.completion); - } - - mutex_unlock(&slsi_start_mutex); - r = wait_for_completion_timeout(&sdev->recovery_stop_completion, - msecs_to_jiffies(sdev->recovery_timeout)); - if (r == 0) - SLSI_INFO(sdev, "recovery_stop_completion timeout\n"); - - mutex_lock(&slsi_start_mutex); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) - reinit_completion(&sdev->recovery_stop_completion); -#else - /*This is how the macro is used in the older verion.*/ - INIT_COMPLETION(sdev->recovery_stop_completion); -#endif - mutex_unlock(&slsi_start_mutex); - - } else { - SLSI_INFO_NODEV("WLAN service remove\n"); - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - hip4_sampler_destroy(sdev, mx); -#endif - - mutex_lock(&slsi_start_mutex); - state = atomic_read(&sdev->cm_if.cm_if_state); - if (state != SCSC_WIFI_CM_IF_STATE_STARTED && - state != SCSC_WIFI_CM_IF_STATE_PROBED && - state != SCSC_WIFI_CM_IF_STATE_STOPPED && - state != SCSC_WIFI_CM_IF_STATE_BLOCKED) { - mutex_unlock(&slsi_start_mutex); - SLSI_INFO_NODEV("state-event error %d\n", state); - return; - } - - service_clean_up_locked(sdev); - mutex_unlock(&slsi_start_mutex); - } -} - -/* Block future HIP runs through the hip_switch */ -static void slsi_hip_block_bh(struct slsi_dev *sdev) -{ - SLSI_WARN(sdev, "HIP state set to #SLSI_HIP_STATE_BLOCKED#\n"); - atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_BLOCKED); -} - -struct scsc_mx_module_client wlan_driver = { - .name = "WLAN driver", - .probe = slsi_wlan_service_probe, - .remove = slsi_wlan_service_remove, -}; - -int slsi_sm_service_driver_register(void) -{ - struct slsi_cm_ctx *ctx = &cm_ctx; - - memset(ctx, 0, sizeof(*ctx)); - mutex_init(&slsi_start_mutex); - scsc_mx_module_register_client_module(&wlan_driver); - - return 0; -} - -void slsi_sm_service_driver_unregister(void) -{ - scsc_mx_module_unregister_client_module(&wlan_driver); -} - -/* start/stop wlan service - * ======================= - */ -void slsi_sm_service_failed(struct slsi_dev *sdev, const char *reason) -{ - int state; - - mutex_lock(&slsi_start_mutex); - - state = atomic_read(&sdev->cm_if.cm_if_state); - if (state != SCSC_WIFI_CM_IF_STATE_STARTED && - state != SCSC_WIFI_CM_IF_STATE_STOPPING) { - mutex_unlock(&slsi_start_mutex); - SLSI_INFO(sdev, "State %d - ignoring event\n", state); - return; - } - - /* Limit the volume of error reports to the core */ - if (!sdev->fail_reported) { - /* This log may be scraped by test systems */ - SLSI_ERR(sdev, "scsc_wifibt: FATAL ERROR: %s\n", reason); - - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_BLOCKED); - slsi_hip_block_bh(sdev); - scsc_mx_service_service_failed(sdev->service, reason); - scsc_mx_service_mif_dump_registers(sdev->service); - sdev->fail_reported = true; - } - - mutex_unlock(&slsi_start_mutex); -} - -/* Is production test mode enabled? */ -bool slsi_is_test_mode_enabled(void) -{ - return EnableTestMode; -} - -/* Is production rf test mode enabled? */ -bool slsi_is_rf_test_mode_enabled(void) -{ - return EnableRfTestMode; -} - -#define SLSI_SM_WLAN_SERVICE_RECOVERY_COMPLETED_TIMEOUT 20000 -#define SLSI_SM_WLAN_SERVICE_RECOVERY_DISABLED_TIMEOUT 2000 - -int slsi_sm_wlan_service_open(struct slsi_dev *sdev) -{ - int err = 0; - int state; - - mutex_lock(&slsi_start_mutex); - state = atomic_read(&sdev->cm_if.cm_if_state); - if (state != SCSC_WIFI_CM_IF_STATE_PROBED && - state != SCSC_WIFI_CM_IF_STATE_STOPPED) { - SLSI_INFO(sdev, "State-event error %d\n", state); - err = -EINVAL; - goto exit; - } - - sdev->recovery_timeout = mxman_recovery_disabled() ? SLSI_SM_WLAN_SERVICE_RECOVERY_DISABLED_TIMEOUT : SLSI_SM_WLAN_SERVICE_RECOVERY_COMPLETED_TIMEOUT; - - /* Open service - will download FW - will set MBOX0 with Starting address */ - SLSI_INFO(sdev, "Open WLAN service\n"); - sdev->service = scsc_mx_service_open(sdev->maxwell_core, SCSC_SERVICE_ID_WLAN, &sdev->mx_wlan_client, &err); - if (!sdev->service) { - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_PROBED); - SLSI_WARN(sdev, "Service open failed\n"); - err = -EINVAL; - goto exit; - } - -exit: - mutex_unlock(&slsi_start_mutex); - return err; -} - -#if defined(CONFIG_SLUB_DEBUG_ON) || defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_DEBUG_RT_MUTEXES) || \ - defined(CONFIG_DEBUG_SPINLOCK) && defined(CONFIG_DEBUG_MUTEXES) && defined(CONFIG_DEBUG_LOCK_ALLOC) || \ - defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_DEBUG_ATOMIC_SLEEP) && defined(CONFIG_DEBUG_LIST) -#define KERNEL_DEBUG_OPTIONS_ENABLED -#endif - -int slsi_sm_wlan_service_start(struct slsi_dev *sdev) -{ - struct slsi_hip4 *hip = &sdev->hip4_inst; - scsc_mifram_ref ref; - int err = 0; - int err2 = 0; - int state; - - mutex_lock(&slsi_start_mutex); - state = atomic_read(&sdev->cm_if.cm_if_state); - SLSI_INFO(sdev, - "Recovery -- Status:%d In_Progress:%d -- cm_if_state:%d\n", - sdev->recovery_status, recovery_in_progress, state); - if (state != SCSC_WIFI_CM_IF_STATE_PROBED && - state != SCSC_WIFI_CM_IF_STATE_STOPPED) { - SLSI_INFO(sdev, "State-event error %d\n", state); - mutex_unlock(&slsi_start_mutex); - return -EINVAL; - } - - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STARTING); - -#ifdef KERNEL_DEBUG_OPTIONS_ENABLED - SLSI_WARN(sdev, "Kernel config debug options are enabled. This might impact the throughput performance.\n"); -#endif - - /* Get RAM from the MIF */ - SLSI_INFO(sdev, "Allocate mifram\n"); - -#ifdef CONFIG_SCSC_PCIE - err = scsc_mx_service_mifram_alloc(sdev->service, 1.5 * 1024 * 1024, &sdev->hip4_inst.hip_ref, 4096); -#else - err = scsc_mx_service_mifram_alloc(sdev->service, 2 * 1024 * 1024, &sdev->hip4_inst.hip_ref, 4096); -#endif - if (err) { - SLSI_WARN(sdev, "scsc_mx_service_mifram_alloc failed err: %d\n", err); - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED); - mutex_unlock(&slsi_start_mutex); - return err; - } - - SLSI_INFO(sdev, "Start HIP\n"); - err = slsi_hip_start(sdev); - if (err) { - SLSI_WARN(sdev, "slsi_hip_start failed err: %d\n", err); - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED); - slsi_hip_stop(sdev); - mutex_unlock(&slsi_start_mutex); - return err; - } - - err = scsc_mx_service_mif_ptr_to_addr(sdev->service, hip->hip_control, &ref); - if (err) { - SLSI_WARN(sdev, "scsc_mx_service_mif_ptr_to_addr failed err: %d\n", err); - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED); - slsi_hip_stop(sdev); - mutex_unlock(&slsi_start_mutex); - return err; - } - - SLSI_INFO(sdev, "Starting WLAN service\n"); - err = scsc_mx_service_start(sdev->service, ref); - if (err) { - SLSI_WARN(sdev, "scsc_mx_service_start failed err: %d\n", err); - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED); - slsi_hip_stop(sdev); - mutex_unlock(&slsi_start_mutex); - return err; - } - err = slsi_hip_setup(sdev); - if (err) { - SLSI_WARN(sdev, "slsi_hip_setup failed err: %d\n", err); - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED); - SLSI_INFO_NODEV("Stopping WLAN service\n"); - err2 = scsc_mx_service_stop(sdev->service); - if (err2) - SLSI_INFO(sdev, "scsc_mx_service_stop failed err2: %d\n", err2); - slsi_hip_stop(sdev); - mutex_unlock(&slsi_start_mutex); - return err; - } - /* Service has started, inform SAP versions to the registered SAPs */ - err = slsi_hip_sap_setup(sdev); - if (err) { - SLSI_WARN(sdev, "slsi_hip_sap_setup failed err: %d\n", err); - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED); - SLSI_INFO_NODEV("Stopping WLAN service\n"); - err2 = scsc_mx_service_stop(sdev->service); - if (err2) - SLSI_INFO(sdev, "scsc_mx_service_stop failed err2: %d\n", err2); - slsi_hip_stop(sdev); - mutex_unlock(&slsi_start_mutex); - return err; - } - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STARTED); - mutex_unlock(&slsi_start_mutex); - return 0; -} - -static void __slsi_sm_wlan_service_stop_wait_locked(struct slsi_dev *sdev) -{ - int r; - - mutex_unlock(&slsi_start_mutex); - r = wait_for_completion_timeout(&sdev->recovery_remove_completion, - msecs_to_jiffies(sdev->recovery_timeout)); - if (r == 0) - SLSI_INFO(sdev, "recovery_remove_completion timeout\n"); - - mutex_lock(&slsi_start_mutex); - sdev->recovery_next_state = SCSC_WIFI_CM_IF_STATE_STOPPED; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) - reinit_completion(&sdev->recovery_remove_completion); -#else - /*This is how the macro is used in the older verion.*/ - INIT_COMPLETION(sdev->recovery_remove_completion); -#endif -} - -void slsi_sm_wlan_service_stop(struct slsi_dev *sdev) -{ - int cm_if_state; - int err = 0; - - mutex_lock(&slsi_start_mutex); - cm_if_state = atomic_read(&sdev->cm_if.cm_if_state); - SLSI_INFO(sdev, - "Recovery -- Status:%d In_Progress:%d -- cm_if_state:%d\n", - sdev->recovery_status, recovery_in_progress, cm_if_state); - - if (cm_if_state == SCSC_WIFI_CM_IF_STATE_BLOCKED) { - __slsi_sm_wlan_service_stop_wait_locked(sdev); - - /* If the wait hasn't timed out, the recovery remove completion - * will have completed properly and the cm_if_state will be - * set to stopped here. If the probe hasn't fired for some reason - * try and do a service_stop regardless, since that's all we can - * do in this situation; hence skip the state check. - */ - goto skip_state_check; - } - - if (cm_if_state != SCSC_WIFI_CM_IF_STATE_STARTED && - cm_if_state != SCSC_WIFI_CM_IF_STATE_REMOVED && - cm_if_state != SCSC_WIFI_CM_IF_STATE_PROBED) { - SLSI_INFO(sdev, "Service not started or incorrect state %d\n", - cm_if_state); - goto exit; - } - - /** - * Note that the SCSC_WIFI_CM_IF_STATE_STOPPING state will inhibit - * auto-recovery mechanism, so be careful not to abuse it: as an - * example if panic happens on start or stop we don't want to - * un-necessarily pass by STOPPING in order to have a successful - * recovery in such a situation. - */ - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPING); -skip_state_check: - SLSI_INFO_NODEV("Stopping WLAN service\n"); - err = scsc_mx_service_stop(sdev->service); - if (err == -EILSEQ) { - /* scsc_mx_service_stop failed since there's a recovery in - * progress, so just wait for it to complete and try again. - */ - SLSI_INFO(sdev, "scsc_mx_service_stop failed err: %d\n", err); - __slsi_sm_wlan_service_stop_wait_locked(sdev); - goto skip_state_check; - } else if (err == -EIO) { - char reason[80]; - - SLSI_INFO(sdev, "scsc_mx_service_stop failed err: %d\n", err); - - /* scsc_mx_service_stop since there was no respons from firmware - * to the stop request. Generate a host initiated panic to reset - * the chip and wait for it to complete. - */ - sdev->recovery_next_state = SCSC_WIFI_CM_IF_STATE_STOPPING; - snprintf(reason, sizeof(reason), "WLAN scsc_mx_service_stop failed"); - - mutex_unlock(&slsi_start_mutex); - slsi_sm_service_failed(sdev, reason); - mutex_lock(&slsi_start_mutex); - - __slsi_sm_wlan_service_stop_wait_locked(sdev); - } else if (err == -EPERM) { - /* Special case when recovery is disabled, otherwise the driver - * will wait forever for recovery that never comes - */ - SLSI_INFO(sdev, "refused due to previous failure, recovery is disabled: %d\n", err); - } else if (err != 0) { - SLSI_INFO(sdev, "scsc_mx_service_stop failed, unknown err: %d\n", err); - } - - atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED); -exit: - mutex_unlock(&slsi_start_mutex); -} - -#define SLSI_SM_WLAN_SERVICE_CLOSE_RETRY 60 -void slsi_sm_wlan_service_close(struct slsi_dev *sdev) -{ - int cm_if_state, r; - - mutex_lock(&slsi_start_mutex); - cm_if_state = atomic_read(&sdev->cm_if.cm_if_state); - if (cm_if_state != SCSC_WIFI_CM_IF_STATE_STOPPED) { - SLSI_INFO(sdev, "Service not stopped. cm_if_state = %d\n", cm_if_state); - - /** - * Close the service if failure has occurred after service has successfully opened - * but before service has attempted to start - */ - if (cm_if_state == SCSC_WIFI_CM_IF_STATE_PROBED) { - SLSI_INFO_NODEV("Closing WLAN service on error\n"); - r = scsc_mx_service_close(sdev->service); - } - goto exit; - } - - SLSI_INFO_NODEV("Closing WLAN service\n"); - scsc_mx_service_mifram_free(sdev->service, sdev->hip4_inst.hip_ref); - - r = scsc_mx_service_close(sdev->service); - if (r == -EIO) { - int retry_counter; - - /** - * Error handling in progress - try and close again later. - * The service close call shall remain blocked until close - * service is successful. Try up to 30 seconds. - */ - for (retry_counter = 0; - SLSI_SM_WLAN_SERVICE_CLOSE_RETRY > retry_counter; - retry_counter++) { - msleep(500); - r = scsc_mx_service_close(sdev->service); - if (r == 0) { - SLSI_INFO(sdev, "scsc_mx_service_close closed after %d attempts\n", - retry_counter + 1); - break; - } - } - - if (retry_counter + 1 == SLSI_SM_WLAN_SERVICE_CLOSE_RETRY) - SLSI_ERR(sdev, "scsc_mx_service_close failed %d times\n", - SLSI_SM_WLAN_SERVICE_CLOSE_RETRY); - } else if (r == -EPERM) { - SLSI_ERR(sdev, "scsc_mx_service_close - recovery is disabled (%d)\n", r); - } - - if (recovery_in_progress) - complete_all(&sdev->recovery_stop_completion); -exit: - mutex_unlock(&slsi_start_mutex); -} diff --git a/drivers/net/wireless/scsc/const.h b/drivers/net/wireless/scsc/const.h deleted file mode 100755 index 470c1dca472c..000000000000 --- a/drivers/net/wireless/scsc/const.h +++ /dev/null @@ -1,54 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef _SLSI_CONST_H__ -#define _SLSI_CONST_H__ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Max number of peers */ -#define SLSI_TDLS_PEER_CONNECTIONS_MAX 4 -#define SLSI_AP_PEER_CONNECTIONS_MAX 10 -/* When SLSI_ADHOC_PEER_CONNECTIONS_MAX is increased to 32, - * method of intiliazing peer_sta_record[] should be carefully changed - * from the present way of static allocation to a dynamic allocation or - * a VIF specific initialization or both. - */ -#define SLSI_ADHOC_PEER_CONNECTIONS_MAX 16 - -/* Max number of indexes */ -#define SLSI_TDLS_PEER_INDEX_MIN 2 -#define SLSI_TDLS_PEER_INDEX_MAX 15 -#define SLSI_PEER_INDEX_MIN 1 -#define SLSI_PEER_INDEX_MAX 16 - -#define SLSI_STA_PEER_QUEUESET 0 - -#define SLSI_BA_TRAFFIC_STREAM_MAX 8 -#define SLSI_BA_BUFFER_SIZE_MAX 64 - -/* Until LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 1) the IE Value for - * HT OPERATION was incorrectly defined as HT INFORMATION - */ -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0)) -#ifndef WLAN_EID_HT_INFORMATION -#define WLAN_EID_HT_INFORMATION 61 -#endif - -#define WLAN_EID_HT_OPERATION WLAN_EID_HT_INFORMATION -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _SLSI_CONST_H__ */ diff --git a/drivers/net/wireless/scsc/debug.c b/drivers/net/wireless/scsc/debug.c deleted file mode 100755 index a3907a060bcf..000000000000 --- a/drivers/net/wireless/scsc/debug.c +++ /dev/null @@ -1,437 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include - -#include "debug.h" -#include "procfs.h" -#include "utils.h" - -#ifndef CONFIG_SCSC_DEBUG_COMPATIBILITY -const int SLSI_INIT_DEINIT; -const int SLSI_NETDEV = 1; -const int SLSI_CFG80211 = 2; -const int SLSI_MLME = 3; -const int SLSI_SUMMARY_FRAMES = 4; -const int SLSI_HYDRA = 5; -const int SLSI_TX = 6; -const int SLSI_RX = 7; -const int SLSI_UDI = 8; - -const int SLSI_WIFI_FCQ = 9; - -const int SLSI_HIP = 10; -const int SLSI_HIP_INIT_DEINIT = 11; -const int SLSI_HIP_FW_DL = 12; -const int SLSI_HIP_SDIO_OP = 13; -const int SLSI_HIP_PS = 14; -const int SLSI_HIP_TH = 15; -const int SLSI_HIP_FH = 16; -const int SLSI_HIP_SIG = 17; - -const int SLSI_FUNC_TRACE = 18; -const int SLSI_TEST = 19; /* Unit test logging */ -const int SLSI_SRC_SINK = 20; -const int SLSI_FW_TEST = 21; -const int SLSI_RX_BA = 22; - -const int SLSI_TDLS = 23; -const int SLSI_GSCAN = 24; -const int SLSI_MBULK = 25; -const int SLSI_FLOWC = 26; -const int SLSI_SMAPPER = 27; -#endif - -static int slsi_dbg_set_param_cb(const char *val, const struct kernel_param *kp); -static int slsi_dbg_get_param_cb(char *buffer, const struct kernel_param *kp); - -static struct kernel_param_ops param_ops_log = { - .set = slsi_dbg_set_param_cb, - .get = slsi_dbg_get_param_cb, -}; - -#define ADD_DEBUG_MODULE_PARAM(name, default_level, filter) \ - int slsi_dbg_lvl_ ## name = default_level; \ - module_param_cb(slsi_dbg_lvl_ ## name, ¶m_ops_log, (void *)&filter, S_IRUGO | S_IWUSR); \ - MODULE_PARM_DESC(slsi_dbg_lvl_ ## name, " Debug levels (0~4) for the " # name " module (0 = off) default=" # default_level) - -#ifndef CONFIG_SCSC_DEBUG_COMPATIBILITY -/* Name, Default, Filter */ -ADD_DEBUG_MODULE_PARAM(init_deinit, 3, SLSI_INIT_DEINIT); -ADD_DEBUG_MODULE_PARAM(netdev, 2, SLSI_NETDEV); -ADD_DEBUG_MODULE_PARAM(cfg80211, 1, SLSI_CFG80211); -ADD_DEBUG_MODULE_PARAM(mlme, 2, SLSI_MLME); -ADD_DEBUG_MODULE_PARAM(summary_frames, 0, SLSI_SUMMARY_FRAMES); -ADD_DEBUG_MODULE_PARAM(hydra, 0, SLSI_HYDRA); -ADD_DEBUG_MODULE_PARAM(tx, 0, SLSI_TX); -ADD_DEBUG_MODULE_PARAM(rx, 0, SLSI_RX); -ADD_DEBUG_MODULE_PARAM(udi, 2, SLSI_UDI); - -ADD_DEBUG_MODULE_PARAM(wifi_fcq, 0, SLSI_WIFI_FCQ); - -ADD_DEBUG_MODULE_PARAM(hip, 0, SLSI_HIP); -ADD_DEBUG_MODULE_PARAM(hip_init_deinit, 0, SLSI_HIP_INIT_DEINIT); -ADD_DEBUG_MODULE_PARAM(hip_fw_dl, 0, SLSI_HIP_FW_DL); -ADD_DEBUG_MODULE_PARAM(hip_sdio_op, 0, SLSI_HIP_SDIO_OP); -ADD_DEBUG_MODULE_PARAM(hip_ps, 0, SLSI_HIP_PS); -ADD_DEBUG_MODULE_PARAM(hip_th, 0, SLSI_HIP_TH); -ADD_DEBUG_MODULE_PARAM(hip_fh, 0, SLSI_HIP_FH); -ADD_DEBUG_MODULE_PARAM(hip_sig, 0, SLSI_HIP_SIG); - -ADD_DEBUG_MODULE_PARAM(func_trace, 0, SLSI_FUNC_TRACE); -ADD_DEBUG_MODULE_PARAM(test, 0, SLSI_TEST); -ADD_DEBUG_MODULE_PARAM(src_sink, 0, SLSI_SRC_SINK); -ADD_DEBUG_MODULE_PARAM(fw_test, 0, SLSI_FW_TEST); -ADD_DEBUG_MODULE_PARAM(rx_ba, 0, SLSI_RX_BA); - -ADD_DEBUG_MODULE_PARAM(tdls, 2, SLSI_TDLS); -ADD_DEBUG_MODULE_PARAM(gscan, 3, SLSI_GSCAN); -ADD_DEBUG_MODULE_PARAM(mbulk, 0, SLSI_MBULK); -ADD_DEBUG_MODULE_PARAM(flowc, 0, SLSI_FLOWC); -ADD_DEBUG_MODULE_PARAM(smapper, 0, SLSI_SMAPPER); - -int slsi_dbg_lvl_all; /* Override all debug modules */ - -int *slsi_dbg_filters[] = { - &slsi_dbg_lvl_init_deinit, - &slsi_dbg_lvl_netdev, - &slsi_dbg_lvl_cfg80211, - &slsi_dbg_lvl_mlme, - &slsi_dbg_lvl_summary_frames, - &slsi_dbg_lvl_hydra, - &slsi_dbg_lvl_tx, - &slsi_dbg_lvl_rx, - &slsi_dbg_lvl_udi, - - &slsi_dbg_lvl_wifi_fcq, - - &slsi_dbg_lvl_hip, - &slsi_dbg_lvl_hip_init_deinit, - &slsi_dbg_lvl_hip_fw_dl, - &slsi_dbg_lvl_hip_sdio_op, - &slsi_dbg_lvl_hip_ps, - &slsi_dbg_lvl_hip_th, - &slsi_dbg_lvl_hip_fh, - &slsi_dbg_lvl_hip_sig, - - &slsi_dbg_lvl_func_trace, - &slsi_dbg_lvl_test, - &slsi_dbg_lvl_src_sink, - &slsi_dbg_lvl_fw_test, - &slsi_dbg_lvl_rx_ba, - - &slsi_dbg_lvl_tdls, - &slsi_dbg_lvl_gscan, - &slsi_dbg_lvl_mbulk, - &slsi_dbg_lvl_flowc, - &slsi_dbg_lvl_smapper, -}; -#else -int slsi_dbg_lvl_compat_all; -module_param(slsi_dbg_lvl_compat_all, int, S_IRUGO | S_IWUSR); - -int *slsi_dbg_filters[] = { - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, - &slsi_dbg_lvl_compat_all, -}; - -int slsi_dbg_lvl_all; /* Override all debug modules */ -#endif - -const int SLSI_DF_MAX = (sizeof(slsi_dbg_filters) / sizeof(slsi_dbg_filters[0])); - -const int SLSI_OVERRIDE_ALL_FILTER = -1; /* This is not a log module but merely a filter option */ - -/* Convert a string containing a decimal value to an integer */ -static int slsi_decstr_to_int(const char *dec_str, int *res) -{ - int tmp_res = 0; - int sign = 0; - const char *tmp_char = dec_str; - - sign = (*tmp_char == '-') ? -1 : ((*tmp_char == '+') ? 1 : 0); - if (sign != 0) - tmp_char++; - - while (*tmp_char) { - if (*tmp_char == '\n') - break; - if ((*tmp_char < '0') || (*tmp_char > '9')) - return -1; - tmp_res = tmp_res * 10 + (*tmp_char - '0'); - tmp_char++; - } - - *res = (sign < 0) ? (-tmp_res) : tmp_res; - return 0; -} - -static int slsi_dbg_set_param_cb(const char *val, const struct kernel_param *kp) -{ - int new_val; - int filter; - - if (slsi_decstr_to_int(val, &new_val) < 0) { - pr_info("%s: failed to convert %s to int\n", __func__, val); - return -1; - } - filter = *((int *)(kp->arg)); - - if (filter < -1 || filter >= SLSI_DF_MAX) { - pr_info("%s: filter %d out of range\n", __func__, filter); - return -1; - } - - if (filter == SLSI_OVERRIDE_ALL_FILTER) { - if (new_val == -1) { - pr_info("Override does not take effect because slsi_dbg_lvl_all=%d\n", new_val); - } else { - int i; - - pr_info("Setting all debug modules to level %d\n", new_val); - for (i = 0; i < SLSI_DF_MAX; i++) - *slsi_dbg_filters[i] = new_val; - - slsi_dbg_lvl_all = new_val; - } - } else { - pr_info("Setting debug module %d to level %d\n", filter, new_val); - *slsi_dbg_filters[filter] = new_val; - } - - return 0; -} - -static int slsi_dbg_get_param_cb(char *buffer, const struct kernel_param *kp) -{ -#define KERN_PARAM_OPS_MAX_BUF_SIZE (4 * 1024) - int filter; - int val = 0; - - filter = *((int *)(kp->arg)); - - if (filter == SLSI_OVERRIDE_ALL_FILTER) - val = slsi_dbg_lvl_all; - else if (filter < 0 || filter >= SLSI_DF_MAX) - pr_info("%s: filter %d out of range\n", __func__, filter); - else - val = *slsi_dbg_filters[filter]; - - return snprintf(buffer, KERN_PARAM_OPS_MAX_BUF_SIZE, "%i", val); -} - -module_param_cb(slsi_dbg_lvl_all, ¶m_ops_log, (void *)&SLSI_OVERRIDE_ALL_FILTER, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(slsi_dbg_lvl_all, "Override debug level (0~4) for all the log modules (-1 = do not override) default=0"); - -#ifdef CONFIG_SCSC_WLAN_SKB_TRACKING -struct slsi_skb_tracker { - spinlock_t lock; - struct list_head tracked; - u32 tracked_count; - u32 tracked_count_max; -}; - -struct slsi_tracked_skb { - struct list_head entry; - const char *file; - int line; - struct sk_buff *skb; -}; - -static struct slsi_skb_tracker skb_tracker; - -void slsi_dbg_track_skb_init(void) -{ - SLSI_DBG4_NODEV(SLSI_TEST, "\n"); - memset(&skb_tracker, 0x00, sizeof(skb_tracker)); - spin_lock_init(&skb_tracker.lock); - INIT_LIST_HEAD(&skb_tracker.tracked); -} - -void slsi_dbg_track_skb_reset(void) -{ - SLSI_DBG4_NODEV(SLSI_TEST, "\n"); - skb_tracker.tracked_count = 0; - skb_tracker.tracked_count_max = 0; -} - -bool slsi_dbg_track_skb_marker_f(struct sk_buff *skb, const char *file, int line) -{ - struct slsi_tracked_skb *t; - struct list_head *pos, *q; - bool r = true; - unsigned long flags; - - if (!skb) - return r; - - spin_lock_irqsave(&skb_tracker.lock, flags); - list_for_each_safe(pos, q, &skb_tracker.tracked) { - t = list_entry(pos, struct slsi_tracked_skb, entry); - if (t->skb == skb) { - SLSI_DBG4_NODEV(SLSI_TEST, "Marker 0x%p: %s:%d\n", skb, file, line); - t->file = file; - t->line = line; - goto exit; - } - } - WARN_ON(1); - SLSI_ERR_NODEV("SKB Not Tracked: %p: %s:%d\n", skb, file, line); - r = false; -exit: - spin_unlock_irqrestore(&skb_tracker.lock, flags); - return r; -} - -void slsi_dbg_track_skb_f(struct sk_buff *skb, gfp_t flags, const char *file, int line) -{ - struct slsi_tracked_skb *t = kmalloc(sizeof(*t), flags); - unsigned long flags_irq; - - if (!t) - return; - - t->file = file; - t->line = line; - t->skb = skb_get(skb); /* Add a reference to the skb */ - SLSI_DBG4_NODEV(SLSI_TEST, "track SKB: 0x%p: %s:%d\n", skb, file, line); - spin_lock_irqsave(&skb_tracker.lock, flags_irq); - list_add(&t->entry, &skb_tracker.tracked); - skb_tracker.tracked_count++; - if (skb_tracker.tracked_count > skb_tracker.tracked_count_max) - skb_tracker.tracked_count_max = skb_tracker.tracked_count; - spin_unlock_irqrestore(&skb_tracker.lock, flags_irq); -} - -bool slsi_dbg_untrack_skb_f(struct sk_buff *skb, const char *file, int line) -{ - struct slsi_tracked_skb *t; - struct list_head *pos, *q; - bool r = true; - unsigned long flags; - - if (!skb) - return r; - - spin_lock_irqsave(&skb_tracker.lock, flags); - list_for_each_safe(pos, q, &skb_tracker.tracked) { - t = list_entry(pos, struct slsi_tracked_skb, entry); - if (t->skb == skb) { - SLSI_DBG4_NODEV(SLSI_TEST, "un-track SKB: 0x%p: %s:%d\n", skb, file, line); - list_del(pos); - kfree_skb(t->skb); /* Free the reference we took */ - kfree(t); - skb_tracker.tracked_count--; - goto exit; - } - } - WARN_ON(1); - SLSI_ERR_NODEV("SKB Not Tracked: %p: %s:%d", skb, file, line); - r = false; -exit: - spin_unlock_irqrestore(&skb_tracker.lock, flags); - return r; -} - -void slsi_dbg_track_skb_report(void) -{ - struct slsi_tracked_skb *t; - struct list_head *pos, *q; - unsigned long flags; - - spin_lock_irqsave(&skb_tracker.lock, flags); - SLSI_INFO_NODEV("Tracked Count Current: %d\n", skb_tracker.tracked_count); - SLSI_INFO_NODEV("Tracked Count Max : %d\n", skb_tracker.tracked_count_max); - list_for_each_safe(pos, q, &skb_tracker.tracked) { - t = list_entry(pos, struct slsi_tracked_skb, entry); - if (skb_shared(t->skb)) - SLSI_ERR_NODEV("SKB Leak: 0x%p: %s:%d\n", t->skb, t->file, t->line); - else - SLSI_ERR_NODEV("SKB Not Untracked: 0x%p: %s:%d\n", t->skb, t->file, t->line); - list_del(pos); - kfree_skb(t->skb); /* Free the reference we took */ - kfree(t); - skb_tracker.tracked_count--; - } - INIT_LIST_HEAD(&skb_tracker.tracked); - spin_unlock_irqrestore(&skb_tracker.lock, flags); -} -#endif diff --git a/drivers/net/wireless/scsc/debug.h b/drivers/net/wireless/scsc/debug.h deleted file mode 100644 index b659e2163afa..000000000000 --- a/drivers/net/wireless/scsc/debug.h +++ /dev/null @@ -1,283 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __DEBUG_H__ -#define __DEBUG_H__ - -#include -#include "dev.h" -#include - -/* Logging modules - * ======================= - */ - -#ifndef CONFIG_SCSC_DEBUG_COMPATIBILITY -extern const int SLSI_INIT_DEINIT; -extern const int SLSI_NETDEV; -extern const int SLSI_CFG80211; -extern const int SLSI_MLME; -extern const int SLSI_SUMMARY_FRAMES; -extern const int SLSI_HYDRA; -extern const int SLSI_TX; -extern const int SLSI_RX; -extern const int SLSI_UDI; - -extern const int SLSI_WIFI_FCQ; - -extern const int SLSI_HIP; -extern const int SLSI_HIP_INIT_DEINIT; -extern const int SLSI_HIP_FW_DL; -extern const int SLSI_HIP_SDIO_OP; -extern const int SLSI_HIP_PS; -extern const int SLSI_HIP_TH; -extern const int SLSI_HIP_FH; -extern const int SLSI_HIP_SIG; - -extern const int SLSI_FUNC_TRACE; -extern const int SLSI_TEST; -extern const int SLSI_SRC_SINK; -extern const int SLSI_FW_TEST; -extern const int SLSI_RX_BA; - -extern const int SLSI_TDLS; -extern const int SLSI_GSCAN; -extern const int SLSI_MBULK; -extern const int SLSI_FLOWC; -extern const int SLSI_SMAPPER; -#endif /* CONFIG_SCSC_DEBUG_COMPATIBILITY */ - -extern int *slsi_dbg_filters[]; - -#ifndef pr_warn -#define pr_warn pr_warning -#endif - -/*---------------------------*/ - -/** - * debug logging functions - * ======================= - */ - -#define SLSI_EWI_NODEV_LABEL "ieee80211 phy.: " -#define SLSI_EWI_DEV(sdev) (likely((sdev) && ((sdev)->wiphy)) ? &((sdev)->wiphy->dev) : NULL) -#define SLSI_EWI_NET_DEV(ndev) (likely(ndev) ? SLSI_EWI_DEV(((struct netdev_vif *)netdev_priv(ndev))->sdev) : NULL) -#define SLSI_EWI_NET_NAME(ndev) (likely(ndev) ? netdev_name(ndev) : NULL) - -#define SLSI_EWI(output, sdev, label, fmt, arg ...) output(SLSI_EWI_DEV(sdev), SCSC_PREFIX label ": %s: " fmt, __func__, ## arg) -#define SLSI_EWI_NET(output, ndev, label, fmt, arg ...) output(SLSI_EWI_NET_DEV(ndev), SCSC_PREFIX "%s: " label ": %s: " fmt, SLSI_EWI_NET_NAME(ndev), __func__, ## arg) -#define SLSI_EWI_NODEV(output, label, fmt, arg ...) output(SLSI_EWI_NODEV_LABEL SCSC_PREFIX label ": %s: " fmt, __func__, ## arg) - -#define SLSI_EWI_HEX(output, klevel, sdev, label, p, len, fmt, arg ...) \ - do { \ - SLSI_EWI(output, sdev, label, fmt, ## arg); \ - print_hex_dump(klevel, SCSC_PREFIX, DUMP_PREFIX_OFFSET, 16, 1, p, len, 0); \ - } while (0) - -#define SLSI_EWI_HEX_NET(output, klevel, dev, label, p, len, fmt, arg ...) \ - do { \ - SLSI_EWI_NET(output, dev, label, fmt, ## arg); \ - print_hex_dump(klevel, SCSC_PREFIX, DUMP_PREFIX_OFFSET, 16, 1, p, len, 0); \ - } while (0) - -#define SLSI_EWI_HEX_NODEV(output, klevel, label, p, len, fmt, arg ...) \ - do { \ - SLSI_EWI_NODEV(output, label, fmt, ## arg); \ - print_hex_dump(klevel, SCSC_PREFIX, DUMP_PREFIX_OFFSET, 16, 1, p, len, 0); \ - } while (0) - -#define SLSI_ERR(sdev, fmt, arg ...) SLSI_EWI(dev_err, sdev, "E", fmt, ## arg) -#define SLSI_WARN(sdev, fmt, arg ...) SLSI_EWI(dev_warn, sdev, "W", fmt, ## arg) -#define SLSI_INFO(sdev, fmt, arg ...) SLSI_EWI(dev_info, sdev, "I", fmt, ## arg) - -#define SLSI_NET_ERR(ndev, fmt, arg ...) SLSI_EWI_NET(dev_err, ndev, "E", fmt, ## arg) -#define SLSI_NET_WARN(ndev, fmt, arg ...) SLSI_EWI_NET(dev_warn, ndev, "W", fmt, ## arg) -#define SLSI_NET_INFO(ndev, fmt, arg ...) SLSI_EWI_NET(dev_info, ndev, "I", fmt, ## arg) - -#define SLSI_ERR_NODEV(fmt, arg ...) SLSI_EWI_NODEV(pr_err, "E", fmt, ## arg) -#define SLSI_WARN_NODEV(fmt, arg ...) SLSI_EWI_NODEV(pr_warn, "W", fmt, ## arg) -#define SLSI_INFO_NODEV(fmt, arg ...) SLSI_EWI_NODEV(pr_info, "I", fmt, ## arg) - -#define SLSI_ERR_HEX(sdev, p, len, fmt, arg ...) SLSI_EWI_HEX(dev_err, KERN_ERR, sdev, "E", p, len, fmt, ## arg) -#define SLSI_WARN_HEX(sdev, p, len, fmt, arg ...) SLSI_EWI_HEX(dev_warn, KERN_WARN, sdev, "W", p, len, fmt, ## arg) -#define SLSI_INFO_HEX(sdev, p, len, fmt, arg ...) SLSI_EWI_HEX(dev_info, KERN_INFO, sdev, "I", p, len, fmt, ## arg) - -#define SLSI_ERR_HEX_NODEV(p, len, fmt, arg ...) SLSI_EWI_HEX_NODEV(pr_err, KERN_ERR, "E", p, len, fmt, ## arg) -#define SLSI_WARN_HEX_NODEV(p, len, fmt, arg ...) SLSI_EWI_HEX_NODEV(pr_warn, KERN_WARN, "W", p, len, fmt, ## arg) -#define SLSI_INFO_HEX_NODEV(p, len, fmt, arg ...) SLSI_EWI_HEX_NODEV(pr_info, KERN_INFO, "I", p, len, fmt, ## arg) - -#ifdef CONFIG_SCSC_WLAN_DEBUG - -#define SLSI_DBG(sdev, filter, dbg_lvl, fmt, arg ...) \ - do { \ - if (unlikely((dbg_lvl) <= *slsi_dbg_filters[filter])) { \ - SLSI_EWI(dev_info, sdev, # dbg_lvl, fmt, ## arg); \ - } \ - } while (0) - -#define SLSI_DBG_NET(ndev, filter, dbg_lvl, fmt, arg ...) \ - do { \ - if (unlikely((dbg_lvl) <= *slsi_dbg_filters[filter])) { \ - SLSI_EWI_NET(dev_info, ndev, # dbg_lvl, fmt, ## arg); \ - } \ - } while (0) - -#define SLSI_DBG_NODEV(filter, dbg_lvl, fmt, arg ...) \ - do { \ - if (unlikely((dbg_lvl) <= *slsi_dbg_filters[filter])) { \ - SLSI_EWI_NODEV(pr_info, # dbg_lvl, fmt, ## arg); \ - } \ - } while (0) - -#define SLSI_DBG1(sdev, filter, fmt, arg ...) SLSI_DBG(sdev, filter, 1, fmt, ## arg) -#define SLSI_DBG2(sdev, filter, fmt, arg ...) SLSI_DBG(sdev, filter, 2, fmt, ## arg) -#define SLSI_DBG3(sdev, filter, fmt, arg ...) SLSI_DBG(sdev, filter, 3, fmt, ## arg) -#define SLSI_DBG4(sdev, filter, fmt, arg ...) SLSI_DBG(sdev, filter, 4, fmt, ## arg) - -#define SLSI_NET_DBG1(ndev, filter, fmt, arg ...) SLSI_DBG_NET(ndev, filter, 1, fmt, ## arg) -#define SLSI_NET_DBG2(ndev, filter, fmt, arg ...) SLSI_DBG_NET(ndev, filter, 2, fmt, ## arg) -#define SLSI_NET_DBG3(ndev, filter, fmt, arg ...) SLSI_DBG_NET(ndev, filter, 3, fmt, ## arg) -#define SLSI_NET_DBG4(ndev, filter, fmt, arg ...) SLSI_DBG_NET(ndev, filter, 4, fmt, ## arg) - -#define SLSI_DBG1_NODEV(filter, fmt, arg ...) SLSI_DBG_NODEV(filter, 1, fmt, ## arg) -#define SLSI_DBG2_NODEV(filter, fmt, arg ...) SLSI_DBG_NODEV(filter, 2, fmt, ## arg) -#define SLSI_DBG3_NODEV(filter, fmt, arg ...) SLSI_DBG_NODEV(filter, 3, fmt, ## arg) -#define SLSI_DBG4_NODEV(filter, fmt, arg ...) SLSI_DBG_NODEV(filter, 4, fmt, ## arg) - -/* Prints LOG_ENTRY if the condition evaluates to TRUE otherwise nothing is printed. */ -#define LOG_CONDITIONALLY(condition, LOG_ENTRY) \ - do { \ - if (unlikely(condition)) \ - LOG_ENTRY; \ - } while (0) - -/* Returns TRUE if the flag is set otherwise returns FALSE. */ -#define LOG_BOOL_FLAG(flag) \ - (flag) ? "TRUE" : "FALSE" - -#define SLSI_DBG_HEX_OUT(sdev, filter, dbg_lvl, p, len, fmt, arg ...) \ - do { \ - if (unlikely((dbg_lvl) <= *slsi_dbg_filters[filter])) { \ - SLSI_EWI_HEX(dev_info, KERN_INFO, sdev, # dbg_lvl, p, len, fmt, ## arg); \ - } \ - } while (0) - -#define SLSI_DBG_HEX_OUT_NET(sdev, filter, dbg_lvl, p, len, fmt, arg ...) \ - do { \ - if (unlikely((dbg_lvl) <= *slsi_dbg_filters[filter])) { \ - SLSI_EWI_HEX_NET(dev_info, KERN_INFO, dev, # dbg_lvl, p, len, fmt, ## arg); \ - } \ - } while (0) - -#define SLSI_DBG_HEX_OUT_NODEV(filter, dbg_lvl, p, len, fmt, arg ...) \ - do { \ - if (unlikely((dbg_lvl) <= *slsi_dbg_filters[filter])) { \ - SLSI_EWI_HEX_NODEV(pr_info, KERN_INFO, # dbg_lvl, p, len, fmt, ## arg); \ - } \ - } while (0) - -#define SLSI_DBG_HEX(sdev, filter, p, len, fmt, arg ...) SLSI_DBG_HEX_OUT(sdev, filter, 4, p, len, fmt, ## arg) -#define SLSI_NET_DBG_HEX(dev, filter, p, len, fmt, arg ...) SLSI_DBG_HEX_OUT_NET(dev, filter, 4, p, len, fmt, ## arg) -#define SLSI_DBG_HEX_NODEV(filter, p, len, fmt, arg ...) SLSI_DBG_HEX_OUT_NODEV(filter, 4, p, len, fmt, ## arg) - -#define FUNC_ENTER(sdev) SLSI_DBG4(sdev, SLSI_FUNC_TRACE, "--->\n") -#define FUNC_EXIT(sdev) SLSI_DBG4(sdev, SLSI_FUNC_TRACE, "<---\n") - -#define FUNC_ENTER_NODEV() SLSI_DBG4_NODEV(SLSI_FUNC_TRACE, "--->\n") -#define FUNC_EXIT_NODEV() SLSI_DBG4_NODEV(SLSI_FUNC_TRACE, "<---\n") - -void slsi_debug_frame(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, const char *prefix); -#else /* CONFIG_SCSC_WLAN_DEBUG */ - -#define SLSI_DBG1(sdev, filter, fmt, arg ...) do {} while (0) -#define SLSI_DBG2(sdev, filter, fmt, arg ...) do {} while (0) -#define SLSI_DBG3(sdev, filter, fmt, arg ...) do {} while (0) -#define SLSI_DBG4(sdev, filter, fmt, arg ...) do {} while (0) -#define SLSI_NET_DBG1(dev, filter, fmt, arg ...) do {} while (0) -#define SLSI_NET_DBG2(dev, filter, fmt, arg ...) do {} while (0) -#define SLSI_NET_DBG3(dev, filter, fmt, arg ...) do {} while (0) -#define SLSI_NET_DBG4(dev, filter, fmt, arg ...) do {} while (0) -#define SLSI_DBG1_NODEV(filter, fmt, arg ...) do {} while (0) -#define SLSI_DBG2_NODEV(filter, fmt, arg ...) do {} while (0) -#define SLSI_DBG3_NODEV(filter, fmt, arg ...) do {} while (0) -#define SLSI_DBG4_NODEV(filter, fmt, arg ...) do {} while (0) - -#define LOG_CONDITIONALLY(condition, LOG_ENTRY) do {} while (0) -#define LOG_BOOL_FLAG(flag) do {} while (0) - -#define SLSI_DBG_HEX(sdev, filter, p, len, fmt, arg ...) do {} while (0) -#define SLSI_NET_DBG_HEX(dev, filter, p, len, fmt, arg ...) do {} while (0) -#define SLSI_DBG_HEX_NODEV(filter, p, len, fmt, arg ...) do {} while (0) - -#define FUNC_ENTER(sdev) -#define FUNC_EXIT(sdev) - -#define FUNC_ENTER_NODEV() -#define FUNC_EXIT_NODEV() - -static inline void slsi_debug_frame(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, const char *prefix) -{ - (void)sdev; /* unused */ - (void)dev; /* unused */ - (void)skb; /* unused */ - (void)prefix; /* unused */ -} - -#endif /* CONFIG_SCSC_WLAN_DEBUG */ - -#ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY - -#undef SLSI_ERR -#undef SLSI_WARN -#undef SLSI_INFO -#define SLSI_ERR(sdev, fmt, arg ...) SCSC_ERR_SDEV(sdev, fmt, ## arg) -#define SLSI_WARN(sdev, fmt, arg ...) SCSC_WARNING_SDEV(sdev, fmt, ## arg) -#define SLSI_INFO(sdev, fmt, arg ...) SCSC_INFO_SDEV(sdev, fmt, ## arg) - -#undef SLSI_NET_ERR -#undef SLSI_NET_WARN -#undef SLSI_NET_INFO -#define SLSI_NET_ERR(ndev, fmt, arg ...) SCSC_ERR_NDEV(ndev, fmt, ## arg) -#define SLSI_NET_WARN(ndev, fmt, arg ...) SCSC_WARNING_NDEV(ndev, fmt, ## arg) -#define SLSI_NET_INFO(ndev, fmt, arg ...) SCSC_INFO_NDEV(ndev, fmt, ## arg) - -#undef SLSI_ERR_NODEV -#undef SLSI_WARN_NODEV -#undef SLSI_INFO_NODEV -#define SLSI_ERR_NODEV(fmt, arg ...) SCSC_ERR(fmt, ## arg) -#define SLSI_WARN_NODEV(fmt, arg ...) SCSC_WARNING(fmt, ## arg) -#define SLSI_INFO_NODEV(fmt, arg ...) SCSC_INFO(fmt, ## arg) - -#undef SLSI_DBG1 -#undef SLSI_DBG2 -#undef SLSI_DBG3 -#undef SLSI_DBG4 -#define SLSI_DBG1(sdev, filter, fmt, arg ...) SCSC_TAG_DBG1_SDEV(sdev, filter, fmt, ## arg) -#define SLSI_DBG2(sdev, filter, fmt, arg ...) SCSC_TAG_DBG2_SDEV(sdev, filter, fmt, ## arg) -#define SLSI_DBG3(sdev, filter, fmt, arg ...) SCSC_TAG_DBG3_SDEV(sdev, filter, fmt, ## arg) -#define SLSI_DBG4(sdev, filter, fmt, arg ...) SCSC_TAG_DBG4_SDEV(sdev, filter, fmt, ## arg) - -#undef SLSI_NET_DBG1 -#undef SLSI_NET_DBG2 -#undef SLSI_NET_DBG3 -#undef SLSI_NET_DBG4 -#define SLSI_NET_DBG1(ndev, filter, fmt, arg ...) SCSC_TAG_DBG1_NDEV(ndev, filter, fmt, ## arg) -#define SLSI_NET_DBG2(ndev, filter, fmt, arg ...) SCSC_TAG_DBG2_NDEV(ndev, filter, fmt, ## arg) -#define SLSI_NET_DBG3(ndev, filter, fmt, arg ...) SCSC_TAG_DBG3_NDEV(ndev, filter, fmt, ## arg) -#define SLSI_NET_DBG4(ndev, filter, fmt, arg ...) SCSC_TAG_DBG4_NDEV(ndev, filter, fmt, ## arg) - -#undef SLSI_DBG1_NODEV -#undef SLSI_DBG2_NODEV -#undef SLSI_DBG3_NODEV -#undef SLSI_DBG4_NODEV -#define SLSI_DBG1_NODEV(filter, fmt, arg ...) SCSC_TAG_DBG1(filter, fmt, ## arg) -#define SLSI_DBG2_NODEV(filter, fmt, arg ...) SCSC_TAG_DBG2(filter, fmt, ## arg) -#define SLSI_DBG3_NODEV(filter, fmt, arg ...) SCSC_TAG_DBG3(filter, fmt, ## arg) -#define SLSI_DBG4_NODEV(filter, fmt, arg ...) SCSC_TAG_DBG4(filter, fmt, ## arg) - -#endif /* CONFIG_SCSC_DEBUG_COMPATIBILITY */ -#endif diff --git a/drivers/net/wireless/scsc/debug_frame.c b/drivers/net/wireless/scsc/debug_frame.c deleted file mode 100755 index eee4efa8ecc3..000000000000 --- a/drivers/net/wireless/scsc/debug_frame.c +++ /dev/null @@ -1,1120 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include - -#include "debug.h" -#include "fapi.h" -#include "const.h" -#include "mgt.h" - -#ifdef CONFIG_SCSC_WLAN_DEBUG - -/* frame decoding debug level */ -static int slsi_debug_summary_frame = 3; -module_param(slsi_debug_summary_frame, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(slsi_debug_summary_frame, "Debug level (0: disable, 1: mgmt only (no scan), 2: mgmt and imp frames, 3: all"); - -struct slsi_decode_entry { - const char *name; - void (*decode_fn)(u8 *frame, u16 frame_length, char *result, size_t result_length); -}; - -struct slsi_decode_snap { - const u8 snap[8]; - const char *name; - size_t (*decode_fn)(u8 *frame, u16 frame_length, char *result, size_t result_length); -}; - -struct slsi_value_name_decode { - const u16 value; - const char *name; - size_t (*decode_fn)(u8 *frame, u16 frame_length, char *result, size_t result_length); -}; - -static size_t slsi_decode_basic_ie_info(u8 *ies, u16 ies_length, char *result, size_t result_length) -{ - size_t size_written = 0; - const u8 *ssid = cfg80211_find_ie(WLAN_EID_SSID, ies, ies_length); - const u8 *rsn = cfg80211_find_ie(WLAN_EID_RSN, ies, ies_length); - const u8 *wpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, ies, ies_length); - const u8 *wps = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, ies, ies_length); - const u8 *htop = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ies, ies_length); - const u8 *country = cfg80211_find_ie(WLAN_EID_COUNTRY, ies, ies_length); - - if (htop && htop[1]) { - size_written += snprintf(result + size_written, result_length - size_written, " channel:%d", htop[2]); - } else { - const u8 *ds = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_length); - - if (ds) - size_written += snprintf(result + size_written, result_length - size_written, " channel:%d", ds[2]); - } - - if (ssid) { - if (ssid[1]) - size_written += snprintf(result + size_written, result_length - size_written, " %.*s", ssid[1], (char *)&ssid[2]); - else - size_written += snprintf(result + size_written, result_length - size_written, " "); - } - - if (country) - size_written += snprintf(result + size_written, result_length - size_written, " country:%c%c%c", country[2], country[3], country[4]); - if (wpa) - size_written += snprintf(result + size_written, result_length - size_written, " wpa"); - if (rsn) - size_written += snprintf(result + size_written, result_length - size_written, " wpa2"); - if (wps) - size_written += snprintf(result + size_written, result_length - size_written, " wps"); - return size_written; -} - -static void slsi_decode_frame_ies_only(u8 offset, u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - size_t str_len; - - result[0] = '('; - str_len = slsi_decode_basic_ie_info(frame + offset, - frame_length - offset, - result + 1, - result_length - 1); - result[1 + str_len] = ')'; - result[2 + str_len] = '\0'; -} - -static size_t slsi_decode_frame_leu16(u8 *frame, u16 frame_length, char *result, size_t result_length, const char *name) -{ - u16 value = frame[0] | frame[1] << 8; - - SLSI_UNUSED_PARAMETER(frame_length); - - return snprintf(result, result_length, "%s:%u", name, value); -} - -#define SLSI_ASSOC_REQ_IE_OFFSET 4 -static void slsi_decode_assoc_req(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - slsi_decode_frame_ies_only(SLSI_ASSOC_REQ_IE_OFFSET, frame, frame_length, result, result_length); -} - -#define SLSI_ASSOC_RSP_STATUS_OFFSET 2 -#define SLSI_ASSOC_RSP_IE_OFFSET 6 -static void slsi_decode_assoc_rsp(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - size_t str_len = 0; - - result[str_len++] = '('; - str_len += slsi_decode_frame_leu16(frame + SLSI_ASSOC_RSP_STATUS_OFFSET, - frame_length - SLSI_ASSOC_RSP_STATUS_OFFSET, - result + str_len, - result_length - str_len, - "status"); - str_len += slsi_decode_basic_ie_info(frame + SLSI_ASSOC_RSP_IE_OFFSET, - frame_length - SLSI_ASSOC_RSP_IE_OFFSET, - result + str_len, - result_length - str_len); - result[str_len++] = ')'; - result[str_len] = '\0'; -} - -#define SLSI_DEAUTH_REASON_OFFSET 0 -static void slsi_decode_deauth(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - size_t str_len = 0; - - result[str_len++] = '('; - str_len += slsi_decode_frame_leu16(frame + SLSI_DEAUTH_REASON_OFFSET, - frame_length - SLSI_DEAUTH_REASON_OFFSET, - result + str_len, - result_length - str_len, - "reason_code"); - result[str_len++] = ')'; - result[str_len] = '\0'; -} - -#define SLSI_AUTH_ALGO_OFFSET 0 -#define SLSI_AUTH_SEQ_OFFSET 2 -#define SLSI_AUTH_STATUS_OFFSET 4 -static void slsi_decode_auth(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - size_t str_len = 0; - - result[str_len++] = '('; - str_len += slsi_decode_frame_leu16(frame + SLSI_AUTH_ALGO_OFFSET, - frame_length - SLSI_AUTH_ALGO_OFFSET, - result + str_len, - result_length - str_len, - "algo"); - result[str_len++] = ' '; - str_len += slsi_decode_frame_leu16(frame + SLSI_AUTH_SEQ_OFFSET, - frame_length - SLSI_AUTH_SEQ_OFFSET, - result + str_len, - result_length - str_len, - "seq"); - result[str_len++] = ' '; - str_len += slsi_decode_frame_leu16(frame + SLSI_AUTH_STATUS_OFFSET, - frame_length - SLSI_AUTH_STATUS_OFFSET, - result + str_len, - result_length - str_len, - "status"); - result[str_len++] = ' '; - result[str_len++] = ')'; - result[str_len] = '\0'; -} - -#define SLSI_REASSOC_IE_OFFSET 10 -static void slsi_decode_reassoc_req(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - slsi_decode_frame_ies_only(SLSI_REASSOC_IE_OFFSET, frame, frame_length, result, result_length); -} - -#define SLSI_BEACON_IE_OFFSET 12 -static void slsi_decode_beacon(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - slsi_decode_frame_ies_only(SLSI_BEACON_IE_OFFSET, frame, frame_length, result, result_length); -} - -#define SLSI_PROBEREQ_IE_OFFSET 0 -static void slsi_decode_probe_req(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - slsi_decode_frame_ies_only(SLSI_PROBEREQ_IE_OFFSET, frame, frame_length, result, result_length); -} - -#define SLSI_ACTION_BLOCK_ACK_ADDBA_REQ 0 -#define SLSI_ACTION_BLOCK_ACK_ADDBA_RSP 1 -#define SLSI_ACTION_BLOCK_ACK_DELBA 2 -static size_t slsi_decode_action_blockack(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u8 action = frame[1]; - - SLSI_UNUSED_PARAMETER(frame_length); - - switch (action) { - case SLSI_ACTION_BLOCK_ACK_ADDBA_REQ: - { - u8 token = frame[2]; - - return snprintf(result, result_length, "->ADDBAReq(token:%u)", token); - } - case SLSI_ACTION_BLOCK_ACK_ADDBA_RSP: - { - u8 token = frame[2]; - u16 status = frame[3] | frame[4] << 8; - - return snprintf(result, result_length, "->ADDBARsp(token:%u, status:%u)", token, status); - } - case SLSI_ACTION_BLOCK_ACK_DELBA: - { - u16 reason_code = frame[4] | frame[5] << 8; - - return snprintf(result, result_length, "->DELBA(reason_code:%u)", reason_code); - } - default: - return snprintf(result, result_length, "->Action(%u)", action); - } -} - -#define SLSI_ACTION_PUBLIC_DISCOVERY_RSP 14 - -static size_t slsi_decode_action_public(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u8 action = frame[1]; - - SLSI_UNUSED_PARAMETER(frame_length); - - switch (action) { - case SLSI_ACTION_PUBLIC_DISCOVERY_RSP: - { - u8 token = frame[2]; - - return snprintf(result, result_length, "->DiscoveryRsp(token:%u)", token); - } - default: - return snprintf(result, result_length, "->Action(%u)", action); - } -} - -#define SLSI_ACTION_TDLS_SETUP_REQ 0 -#define SLSI_ACTION_TDLS_SETUP_RSP 1 -#define SLSI_ACTION_TDLS_SETUP_CFM 2 -#define SLSI_ACTION_TDLS_TEARDOWN 3 -#define SLSI_ACTION_TDLS_PEER_TRAFFIC_IND 4 -#define SLSI_ACTION_TDLS_CHANNEL_SWITCH_REQ 5 -#define SLSI_ACTION_TDLS_CHANNEL_SWITCH_RSP 6 -#define SLSI_ACTION_TDLS_PEER_PSM_REQ 7 -#define SLSI_ACTION_TDLS_PEER_PSM_RSP 8 -#define SLSI_ACTION_TDLS_PEER_TRAFFIC_RSP 9 -#define SLSI_ACTION_TDLS_DISCOVERY_REQ 10 - -static size_t slsi_decode_action_tdls(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u8 action = frame[1]; - - SLSI_UNUSED_PARAMETER(frame_length); - - switch (action) { - case SLSI_ACTION_TDLS_SETUP_REQ: - { - u8 token = frame[2]; - - return snprintf(result, result_length, "->SetupReq(token:%u)", token); - } - case SLSI_ACTION_TDLS_SETUP_RSP: - { - u16 status = frame[2] | frame[3] << 8; - u8 token = frame[4]; - - return snprintf(result, result_length, "->SetupRsp(token:%u, status:%u)", token, status); - } - case SLSI_ACTION_TDLS_SETUP_CFM: - { - u16 status = frame[2] | frame[3] << 8; - u8 token = frame[4]; - - return snprintf(result, result_length, "->SetupCfm(token:%u, status:%u)", token, status); - } - case SLSI_ACTION_TDLS_TEARDOWN: - { - u16 reason = frame[2] | frame[3] << 8; - - return snprintf(result, result_length, "->SetupCfm(reason:%u)", reason); - } - case SLSI_ACTION_TDLS_PEER_TRAFFIC_IND: - { - u8 token = frame[2]; - - return snprintf(result, result_length, "->PeerTrafficInd(token:%u)", token); - } - case SLSI_ACTION_TDLS_CHANNEL_SWITCH_REQ: - { - u8 channel = frame[2]; - - return snprintf(result, result_length, "->ChannelSwitchReq(channel:%u)", channel); - } - case SLSI_ACTION_TDLS_CHANNEL_SWITCH_RSP: - { - u16 status = frame[2] | frame[3] << 8; - - return snprintf(result, result_length, "->ChannelSwitchRsp(status:%u)", status); - } - case SLSI_ACTION_TDLS_PEER_PSM_REQ: - { - u8 token = frame[2]; - - return snprintf(result, result_length, "->PeerPSMReq(token:%u)", token); - } - case SLSI_ACTION_TDLS_PEER_PSM_RSP: - { - u8 token = frame[2]; - u16 status = frame[3] | frame[4] << 8; - - return snprintf(result, result_length, "->PeerPSMRsp(token:%u, status:%u)", token, status); - } - case SLSI_ACTION_TDLS_PEER_TRAFFIC_RSP: - { - u8 token = frame[2]; - - return snprintf(result, result_length, "->PeerTrafficRsp(token:%u)", token); - } - case SLSI_ACTION_TDLS_DISCOVERY_REQ: - { - u8 token = frame[2]; - - return snprintf(result, result_length, "->DiscoveryReq(token:%u)", token); - } - default: - return snprintf(result, result_length, "->Action(%u)", action); - } -} - -static const struct slsi_value_name_decode action_categories[] = { - { 3, "BlockAck", slsi_decode_action_blockack }, - { 0, "SpectrumManagement", NULL }, - { 1, "QoS", NULL }, - { 2, "DLS", NULL }, - { 4, "Public", slsi_decode_action_public }, - { 5, "RadioMeasurement", NULL }, - { 6, "FastBSSTransition", NULL }, - { 7, "HT", NULL }, - { 8, "SAQuery", NULL }, - { 9, "ProtectedDualOfPublicAction", NULL }, - { 12, "TDLS", slsi_decode_action_tdls }, - { 17, "ReservedWFA", NULL }, - { 126, "VendorSpecificProtected", NULL }, - { 127, "VendorSpecific", NULL }, - { 132, "Public(error)", slsi_decode_action_public }, -}; - -#define SLSI_ACTION_CAT_BLOCK_ACK 3 -static void slsi_decode_action(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u8 category = frame[0]; - u32 i; - - for (i = 0; i < ARRAY_SIZE(action_categories); i++) - if (action_categories[i].value == category) { - int size_written = snprintf(result, result_length, "->%s", action_categories[i].name); - - if (action_categories[i].decode_fn) - action_categories[i].decode_fn(frame, frame_length, result + size_written, result_length - size_written); - return; - } - snprintf(result, result_length, "->category:%u", category); -} - -const char *slsi_arp_opcodes[] = { - "Reserved", - "REQUEST", - "REPLY", - "request Reverse", - "reply Reverse", - "DRARP-Request", - "DRARP-Reply", - "DRARP-Error", - "InARP-Request", - "InARP-Reply", - "ARP-NAK", - "MARS-Request", - "MARS-Multi", - "MARS-MServ", - "MARS-Join", - "MARS-Leave", - "MARS-NAK", - "MARS-Unserv", - "MARS-SJoin", - "MARS-SLeave", - "MARS-Grouplist-Request", - "MARS-Grouplist-Reply", - "MARS-Redirect-Map", - "MAPOS-UNARP", - "OP_EXP1", - "OP_EXP2", -}; - -static size_t slsi_decode_arp(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - /* u16 htype = frame[0] << 8 | frame[1]; - * u16 proto = frame[2] << 8 | frame[3]; - * u8 hlen = frame[4]; - * u8 plen = frame[5]; - */ - u16 opcode = frame[6] << 8 | frame[7]; - u8 *sha = &frame[8]; - u8 *spa = &frame[14]; - u8 *tha = &frame[18]; - u8 *tpa = &frame[24]; - - SLSI_UNUSED_PARAMETER(frame_length); - - if (opcode < ARRAY_SIZE(slsi_arp_opcodes)) - return snprintf(result, result_length, "->%s(sha:%.2X:%.2X:%.2X:%.2X:%.2X:%.2X, spa:%u.%u.%u.%u, tha:%.2X:%.2X:%.2X:%.2X:%.2X:%.2X, tpa:%u.%u.%u.%u)", - slsi_arp_opcodes[opcode], - sha[0], sha[1], sha[2], sha[3], sha[4], sha[5], - spa[0], spa[1], spa[2], spa[3], - tha[0], tha[1], tha[2], tha[3], tha[4], tha[5], - tpa[0], tpa[1], tpa[2], tpa[3]); - else - return snprintf(result, result_length, "->(opcode:%u)", opcode); -} - -static const struct slsi_value_name_decode slsi_decode_eapol_packet_types[] = { - { 1, "Identity", NULL }, - { 2, "Notification", NULL }, - { 3, "Nak", NULL }, - { 4, "MD5Challenge", NULL }, - { 5, "OneTimePassword", NULL }, - { 6, "GenericTokenCard", NULL }, - { 9, "RSA Public Key Authentication", NULL }, - { 10, "DSS Unilateral", NULL }, - { 11, "KEA", NULL }, - { 12, "KEA-VALIDATE", NULL }, - { 13, "EAP-TLS", NULL }, - { 14, "Defender Token (AXENT)", NULL }, - { 15, "RSA Security SecurID EAP", NULL }, - { 16, "Arcot Systems EAP", NULL }, - { 17, "EAP-Cisco Wireless", NULL }, - { 18, "EAP-SIM", NULL }, - { 19, "SRP-SHA1 Part 1", NULL }, - { 21, "EAP-TTLS", NULL }, - { 22, "Remote Access Service", NULL }, - { 23, "EAP-AKA", NULL }, - { 24, "EAP-3Com Wireless", NULL }, - { 25, "PEAP", NULL }, - { 26, "MS-EAP-Authentication", NULL }, - { 27, "MAKE", NULL }, - { 28, "CRYPTOCard", NULL }, - { 29, "EAP-MSCHAP-V2", NULL }, - { 30, "DynamID", NULL }, - { 31, "Rob EAP", NULL }, - { 32, "EAP-POTP", NULL }, - { 33, "MS-Authentication-TLV", NULL }, - { 34, "SentriNET", NULL }, - { 35, "EAP-Actiontec Wireless", NULL }, - { 36, "Cogent Systems Biometrics Authentication EAP", NULL }, - { 37, "AirFortress EAP", NULL }, - { 38, "EAP-HTTP Digest", NULL }, - { 39, "SecureSuite EAP", NULL }, - { 40, "DeviceConnect EAP", NULL }, - { 41, "EAP-SPEKE", NULL }, - { 42, "EAP-MOBAC", NULL }, - { 43, "EAP-FAST", NULL }, - { 44, "ZLXEAP", NULL }, - { 45, "EAP-Link", NULL }, - { 46, "EAP-PAX", NULL }, - { 47, "EAP-PSK", NULL }, - { 48, "EAP-SAKE", NULL }, - { 49, "EAP-IKEv2", NULL }, - { 50, "EAP-AKA", NULL }, - { 51, "EAP-GPSK", NULL }, - { 52, "EAP-pwd", NULL }, - { 53, "EAP-EKE V1", NULL }, - { 254, "WPS", NULL } -}; - -static size_t slsi_decode_eapol_packet(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - static const char *const slsi_decode_eapol_packet_codes[] = { - "", - "Request", - "Response", - "Success", - "Failure", - }; - - size_t size_written = 0; - u32 i; - u8 code = frame[0]; - u8 id = frame[1]; - u16 length = frame[2] << 8 | frame[3]; - const char *code_str = ""; - - SLSI_UNUSED_PARAMETER(frame_length); - - if (code >= 1 && code <= 4) - code_str = slsi_decode_eapol_packet_codes[code]; - - if (length > 4 && (code == 1 || code == 2)) { - u8 type = frame[4]; - - for (i = 0; i < ARRAY_SIZE(slsi_decode_eapol_packet_types); i++) - if (slsi_decode_eapol_packet_types[i].value == type) { - size_written += snprintf(result, result_length, ":%s:%s id:%u", slsi_decode_eapol_packet_types[i].name, code_str, id); - return size_written; - } - size_written += snprintf(result, result_length, ":type:%u: %s id:%u", type, code_str, id); - } else { - size_written += snprintf(result, result_length, ":%s id:%u length:%u", code_str, id, length); - } - return size_written; -} - -static const struct slsi_value_name_decode slsi_eapol_packet_type[] = { - { 0, "EapPacket", slsi_decode_eapol_packet }, - { 1, "EapolStart", NULL }, - { 2, "EapolLogoff", NULL }, - { 3, "EapolKey", NULL } -}; - -static size_t slsi_decode_eapol(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - size_t size_written = 0; - u8 packet_type = frame[1]; - u16 length = frame[2] << 8 | frame[3]; - - SLSI_UNUSED_PARAMETER(frame_length); - - if (packet_type < ARRAY_SIZE(slsi_eapol_packet_type)) { - size_written += snprintf(result, result_length, "->%s", slsi_eapol_packet_type[packet_type].name); - if (slsi_eapol_packet_type[packet_type].decode_fn) - size_written += slsi_eapol_packet_type[packet_type].decode_fn(frame + 4, length, result + size_written, result_length - size_written); - return size_written; - } else { - return snprintf(result, result_length, "->packet_type:%u", packet_type); - } -} - -static size_t slsi_decode_tdls(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u8 payload_type = frame[0]; - - if (payload_type == 2) { - slsi_decode_action(frame + 1, frame_length - 1, result, result_length); - return 0; - } else { - return snprintf(result, result_length, "->Unknown(payload:%u", payload_type); - } -} - -static size_t slsi_decode_ipv4_icmp_echo(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u16 id = frame[0] << 8 | frame[1]; - u16 seq = frame[2] << 8 | frame[3]; - - SLSI_UNUSED_PARAMETER(frame_length); - - return snprintf(result, result_length, " id:%u seq:%u", id, seq); -} - -static const struct slsi_value_name_decode slsi_ipv4_icmp_types[] = { - { 0, "EchoReply", slsi_decode_ipv4_icmp_echo }, - { 8, "Echo ", slsi_decode_ipv4_icmp_echo }, - { 3, "Destination Unreachable Ack", NULL }, - { 4, "Source Quench", NULL }, - { 5, "Redirect", NULL }, - { 6, "Alternate Host Address", NULL }, - { 9, "Router Advertisement", NULL }, - { 10, "Router Selection", NULL }, - { 11, "Time Exceeded", NULL }, - { 12, "Parameter Problem", NULL }, - { 13, "Timestamp", NULL }, - { 14, "Timestamp Reply", NULL }, - { 15, "Information Request", NULL }, - { 16, "Information Reply", NULL }, - { 17, "Address Mask Request", NULL }, - { 18, "Address Mask Reply", NULL }, - { 19, "Reserved (for Security)", NULL }, - { 30, "Traceroute", NULL }, - { 31, "Datagram Conversion Error", NULL }, - { 32, "Mobile Host Redirect", NULL }, - { 33, "IPv6 Where-Are-You", NULL }, - { 34, "IPv6 I-Am-Here", NULL }, - { 35, "Mobile Registration Request", NULL }, - { 36, "Mobile Registration Reply", NULL }, - { 39, "SKIP", NULL }, - { 40, "Photuris", NULL }, - { 253, "RFC3692-style Experiment 1", NULL }, - { 254, "RFC3692-style Experiment 2", NULL } -}; - -static size_t slsi_decode_ipv4_icmp(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - size_t size_written = 0; - u32 i; - u8 type = frame[0]; - u8 code = frame[1]; - - for (i = 0; i < ARRAY_SIZE(slsi_ipv4_icmp_types); i++) - if (slsi_ipv4_icmp_types[i].value == type) { - size_written += snprintf(result, result_length, "->%s(code:%u)", slsi_ipv4_icmp_types[i].name, code); - if (slsi_ipv4_icmp_types[i].decode_fn) - size_written += slsi_ipv4_icmp_types[i].decode_fn(frame + 4, frame_length - 4, result + size_written, result_length - size_written); - return size_written; - } - return snprintf(result, result_length, "->type(%u)", type); -} - -static const struct slsi_value_name_decode slsi_ipv4_udp_bootp_dhcp_option53[] = { - { 1, "DHCP_DISCOVER", NULL }, - { 2, "DHCP_OFFER", NULL }, - { 3, "DHCP_REQUEST", NULL }, - { 4, "DHCP_DECLINE", NULL }, - { 5, "DHCP_ACK", NULL }, - { 6, "DHCP_NAK", NULL }, - { 7, "DHCP_RELEASE", NULL }, - { 8, "DHCP_INFORM", NULL }, -}; - -#define SLSI_IPV4_UDP_BOOTP_CIADDR_OFFSET 16 -#define SLSI_IPV4_UDP_BOOTP_YIADDR_OFFSET 20 -#define SLSI_IPV4_UDP_BOOTP_GIADDR_OFFSET 24 -#define SLSI_IPV4_UDP_BOOTP_MAGIC_OFFSET 236 -static size_t slsi_decode_ipv4_udp_bootp(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u32 i; - u8 *ciaddr = &frame[SLSI_IPV4_UDP_BOOTP_CIADDR_OFFSET]; - u8 *yiaddr = &frame[SLSI_IPV4_UDP_BOOTP_YIADDR_OFFSET]; - u8 *giaddr = &frame[SLSI_IPV4_UDP_BOOTP_GIADDR_OFFSET]; - u8 *magic = &frame[SLSI_IPV4_UDP_BOOTP_MAGIC_OFFSET]; - - if (magic[0] == 0x63 && magic[1] == 0x82 && magic[2] == 0x53 && magic[3] == 0x63) { - u8 *p = &frame[SLSI_IPV4_UDP_BOOTP_MAGIC_OFFSET + 4]; - - while (p < p + frame_length) { - u8 option = p[0]; - u8 option_length = p[1]; - - if (option == 53 && option_length == 1) { - for (i = 0; i < ARRAY_SIZE(slsi_ipv4_udp_bootp_dhcp_option53); i++) - if (slsi_ipv4_udp_bootp_dhcp_option53[i].value == p[2]) - return snprintf(result, result_length, "->%s(ci:%u.%u.%u.%u yi:%u.%u.%u.%u gi:%u.%u.%u.%u)", - slsi_ipv4_udp_bootp_dhcp_option53[i].name, - ciaddr[0], ciaddr[1], ciaddr[2], ciaddr[3], - yiaddr[0], yiaddr[1], yiaddr[2], yiaddr[3], - giaddr[0], giaddr[1], giaddr[2], giaddr[3]); - return snprintf(result, result_length, "->option53(%u ci:%u.%u.%u.%u yi:%u.%u.%u.%u gi:%u.%u.%u.%u)", - p[2], - ciaddr[0], ciaddr[1], ciaddr[2], ciaddr[3], - yiaddr[0], yiaddr[1], yiaddr[2], yiaddr[3], - giaddr[0], giaddr[1], giaddr[2], giaddr[3]); - } - if (option == 0) - break; - p = p + 2 + option_length; - } - } - return 0; -} - -static const struct slsi_value_name_decode slsi_ipv4_udp_ports[] = { - { 53, "DNS", NULL }, - { 67, "Bootp", slsi_decode_ipv4_udp_bootp }, - { 68, "Bootp", slsi_decode_ipv4_udp_bootp }, -}; - -static size_t slsi_decode_ipv4_udp(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - /* 0 7 8 15 16 23 24 31 - * +--------+--------+--------+--------+ - * | Source | Destination | - * | Port | Port | - * +--------+--------+--------+--------+ - * | | | - * | Length | Checksum | - * +--------+--------+--------+--------+ - * | - * | data octets ... - * +--------------------- ... - */ - size_t size_written = 0; - u32 i; - u16 sport = frame[0] << 8 | frame[1]; - u16 dport = frame[2] << 8 | frame[3]; - u16 length = frame[4] << 8 | frame[5]; - - /*u16 chksum = frame[6] << 8 | frame[7];*/ - - for (i = 0; i < ARRAY_SIZE(slsi_ipv4_udp_ports); i++) - if (slsi_ipv4_udp_ports[i].value == dport || slsi_ipv4_udp_ports[i].value == sport) { - size_written += snprintf(result, result_length, "->%s", slsi_ipv4_udp_ports[i].name); - if (slsi_ipv4_udp_ports[i].decode_fn) - size_written += slsi_ipv4_udp_ports[i].decode_fn(frame + 8, length, result + size_written, result_length - size_written); - else - size_written += snprintf(result + size_written, result_length - size_written, "(dport:%u, size:%u)", dport, frame_length - 8); - return size_written; - } - return snprintf(result, result_length, "(dport:%u, size:%u)", dport, frame_length - 8); -} - -static size_t slsi_decode_ipv4_tcp(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - /* TCP Header Format - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Source Port | Destination Port | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Sequence Number | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Acknowledgment Number | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Data | |U|A|P|R|S|F| | - * | Offset| Reserved |R|C|S|S|Y|I| Window | - * | | |G|K|H|T|N|N| | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Checksum | Urgent Pointer | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Options | Padding | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | data | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - u16 dport = frame[2] << 8 | frame[3]; - u8 flags = frame[13]; - bool fin = flags & 0x01; - bool syn = flags & 0x02; - bool rst = flags & 0x04; - bool psh = flags & 0x08; - bool ack = flags & 0x10; - bool urg = flags & 0x20; - - return snprintf(result, result_length, "(dport:%u%s%s%s%s%s%s size:%u)", - dport, - fin ? " FIN" : "", - syn ? " SYN" : "", - rst ? " RST" : "", - psh ? " PSH" : "", - ack ? " ACK" : "", - urg ? " URG" : "", - frame_length - 24); -} - -#define SLSI_IPV4_PROTO_ICMP 1 -#define SLSI_IPV4_PROTO_IGMP 2 -#define SLSI_IPV4_PROTO_TCP 6 -#define SLSI_IPV4_PROTO_UDP 17 -static size_t slsi_decode_ipv4(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - size_t size_written = 0; - u16 ip_data_offset = 20; - /*u8 version = frame[0] >> 4; */ - u8 hlen = frame[0] & 0x0F; - /*u8 tos = frame[1]; */ - /*u16 len = frame[2] << 8 | frame[3]; */ - /*u16 id = frame[4] << 8 | frame[5]; */ - /*u16 flags_foff = frame[6] << 8 | frame[7]; */ - /*u8 ttl = frame[8]; */ - u8 proto = frame[9]; - /*u16 cksum = frame[10] << 8 | frame[11]; */ - u8 *src_ip = &frame[12]; - u8 *dest_ip = &frame[16]; - - if (hlen > 5) - ip_data_offset += (hlen - 5) * 4; - - size_written += snprintf(result + size_written, result_length - size_written, "(s:%u.%u.%u.%u d:%u.%u.%u.%u)", - src_ip[0], src_ip[1], src_ip[2], src_ip[3], - dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]); - - switch (proto) { - case SLSI_IPV4_PROTO_TCP: - size_written += snprintf(result + size_written, result_length - size_written, "->TCP"); - size_written += slsi_decode_ipv4_tcp(frame + ip_data_offset, - frame_length - ip_data_offset, - result + size_written, - result_length - size_written); - break; - case SLSI_IPV4_PROTO_UDP: - size_written += snprintf(result + size_written, result_length - size_written, "->UDP"); - size_written += slsi_decode_ipv4_udp(frame + ip_data_offset, - frame_length - ip_data_offset, - result + size_written, - result_length - size_written); - break; - case SLSI_IPV4_PROTO_ICMP: - size_written += snprintf(result + size_written, result_length - size_written, "->ICMP"); - size_written += slsi_decode_ipv4_icmp(frame + ip_data_offset, - frame_length - ip_data_offset, - result + size_written, - result_length - size_written); - break; - case SLSI_IPV4_PROTO_IGMP: - size_written += snprintf(result + size_written, result_length - size_written, "->IGMP"); - break; - default: - size_written += snprintf(result + size_written, result_length - size_written, "->proto:%u", proto); - break; - } - return size_written; -} - -static const struct slsi_decode_snap snap_types[] = { - { { 0x08, 0x00 }, "IpV4", slsi_decode_ipv4 }, - { { 0x08, 0x06 }, "Arp", slsi_decode_arp }, - { { 0x88, 0x8e }, "Eapol", slsi_decode_eapol }, - { { 0x89, 0x0d }, NULL, slsi_decode_tdls }, - { { 0x86, 0xdd }, "IpV6", NULL }, - { { 0x88, 0xb4 }, "Wapi", NULL }, -}; - -static void slsi_decode_proto_data(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - u32 i; - - for (i = 0; i < ARRAY_SIZE(snap_types); i++) - if (memcmp(snap_types[i].snap, frame, 2) == 0) { - int slen = 0; - - if (snap_types[i].name) - slen = snprintf(result, result_length, "->%s", snap_types[i].name); - if (snap_types[i].decode_fn) - slen += snap_types[i].decode_fn(frame + 2, frame_length - 2, result + slen, result_length - slen); - return; - } - - snprintf(result, result_length, "(proto:0x%.2X%.2X)", frame[0], frame[1]); -} - -static void slsi_decode_80211_data(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - return slsi_decode_proto_data(frame + 6, frame_length - 6, result, result_length); -} - -static const struct slsi_decode_entry frame_types[4][16] = { - { - { "AssocReq", slsi_decode_assoc_req }, - { "AssocRsp", slsi_decode_assoc_rsp }, - { "ReassocReq", slsi_decode_reassoc_req }, - { "ReassocRsp", slsi_decode_assoc_rsp }, /* Same as Assoc Req Frame*/ - { "ProbeReq", slsi_decode_probe_req }, - { "ProbeRsp", slsi_decode_beacon }, /* Same as Beacon Frame */ - { "TimingAdv", NULL }, - { "Reserved", NULL }, - { "Beacon ", slsi_decode_beacon }, - { "Atim", NULL }, - { "Disassoc", slsi_decode_deauth }, /* Same as Deauth Frame */ - { "Auth", slsi_decode_auth }, - { "Deauth", slsi_decode_deauth }, - { "Action", slsi_decode_action }, - { "ActionNoAck", slsi_decode_action }, - { "Reserved", NULL } - }, - { - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "BlockAckReq", NULL }, - { "BlockAck", NULL }, - { "PsPoll", NULL }, - { "RTS", NULL }, - { "CTS", NULL }, - { "Ack", NULL }, - { "CF-End", NULL }, - { "CF-End+Ack", NULL } - }, - { - { "Data", slsi_decode_80211_data }, - { "Data+CF-Ack", slsi_decode_80211_data }, - { "Data+CF-Poll", slsi_decode_80211_data }, - { "Data+CF-Ack+Poll", slsi_decode_80211_data }, - { "Null", NULL }, - { "CF-Ack", NULL }, - { "CF-Poll", NULL }, - { "CF-Ack+Poll", NULL }, - { "QosData", slsi_decode_80211_data }, - { "QosData+CF-Ack", slsi_decode_80211_data }, - { "QosData+CF-Poll", slsi_decode_80211_data }, - { "QosData+CF-Ack+Poll", slsi_decode_80211_data }, - { "QosNull", NULL }, - { "Reserved", NULL }, - { "QosCF-Poll", NULL }, - { "QosCF-Ack+Poll", NULL } - }, - { - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - { "Reserved", NULL }, - } -}; - -static bool slsi_decode_80211_frame(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)frame; - u16 fc_cpu = cpu_to_le16(hdr->frame_control); - int ftype_idx = (fc_cpu & 0xf) >> 2; - const struct slsi_decode_entry *entry; - int hdrlen; - int slen; - - /* Only decode Management Frames at Level 1 */ - if (slsi_debug_summary_frame == 1 && ftype_idx != 0) - return false; - - /* Filter Scanning at the debug level 3 and above as it can be noisy with large scan results */ - if (slsi_debug_summary_frame < 3 && - (ieee80211_is_probe_req(fc_cpu) || ieee80211_is_probe_resp(fc_cpu) || ieee80211_is_beacon(fc_cpu))) - return false; - - entry = &frame_types[ftype_idx][(fc_cpu >> 4) & 0xf]; - hdrlen = ieee80211_hdrlen(hdr->frame_control); - slen = snprintf(result, result_length, entry->name); - - if (entry->decode_fn) - entry->decode_fn(frame + hdrlen, frame_length - hdrlen, result + slen, result_length - slen); - return true; -} - -static bool slsi_decode_l3_frame(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - int slen; - - /* Only decode Management Frames at Level 1 */ - if (slsi_debug_summary_frame == 1) - return false; - - /* Only decode high important frames e.g. EAPOL, ARP, DHCP at Level 2 */ - if (slsi_debug_summary_frame == 2) { - struct ethhdr *ehdr = (struct ethhdr *)frame; - u16 eth_type = be16_to_cpu(ehdr->h_proto); - - switch (eth_type) { - case ETH_P_IP: - if (slsi_is_dhcp_packet(frame) == SLSI_TX_IS_NOT_DHCP) - return false; - break; - /* Fall through; process EAPOL, WAPI and ARP frames */ - case ETH_P_PAE: - case ETH_P_WAI: - case ETH_P_ARP: - break; - default: - /* return for all other frames */ - return false; - } - } - slen = snprintf(result, result_length, "eth"); - slsi_decode_proto_data(frame + 12, frame_length - 12, result + slen, result_length - slen); - return true; -} - -static bool slsi_decode_amsdu_subframe(u8 *frame, u16 frame_length, char *result, size_t result_length) -{ - int slen; - - /* Only decode Management Frames at Level 1 */ - if (slsi_debug_summary_frame == 1) - return false; - - /* Only decode high important frames e.g. EAPOL, ARP, DHCP at Level 2 */ - if (slsi_debug_summary_frame == 2) { - struct msduhdr *msdu_hdr = (struct msduhdr *)frame; - u16 eth_type = be16_to_cpu(msdu_hdr->type); - - switch (eth_type) { - case ETH_P_IP: - /* slsi_is_dhcp_packet() decodes the frame as Ethernet frame so - * pass a offset (difference between MSDU header and ethernet header) - * to frames so it reads at the right offset - */ - if (slsi_is_dhcp_packet(frame + 8) == SLSI_TX_IS_NOT_DHCP) - return false; - break; - /* Fall through; process EAPOL, WAPI and ARP frames */ - case ETH_P_PAE: - case ETH_P_WAI: - case ETH_P_ARP: - break; - default: - /* return for all other frames */ - return false; - } - } - slen = snprintf(result, result_length, "eth"); - slsi_decode_proto_data(frame + 20, frame_length - 20, result + slen, result_length - slen); - return true; -} - -static inline bool slsi_debug_frame_ratelimited(void) -{ - static DEFINE_RATELIMIT_STATE(_rs, (5 * HZ), 200); - - if (__ratelimit(&_rs)) - return true; - return false; -} - -/* NOTE: dev can be NULL */ -void slsi_debug_frame(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, const char *prefix) -{ - char frame_info[384]; - u8 *frame = fapi_get_data(skb); - u16 len = fapi_get_datalen(skb); - u8 *dst = NULL; - u8 *src = NULL; - u16 frametype = 0xFFFF; - bool print = false; - u16 id = fapi_get_sigid(skb); - u16 vif = fapi_get_vif(skb); - s16 rssi = 0; - - if (!slsi_debug_summary_frame) - return; - - if (!len) - return; - - switch (id) { - case MA_UNITDATA_REQ: - case MA_UNITDATA_IND: - if (!slsi_debug_frame_ratelimited()) /* Limit the Data output to stop too much spam at high data rates */ - return; - break; - default: - break; - } - - frame_info[0] = '\0'; - switch (id) { - case MA_UNITDATA_REQ: - frametype = fapi_get_u16(skb, u.ma_unitdata_req.data_unit_descriptor); - break; - case MA_UNITDATA_IND: - frametype = fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor); - break; - case MLME_SEND_FRAME_REQ: - frametype = fapi_get_u16(skb, u.mlme_send_frame_req.data_unit_descriptor); - break; - case MLME_RECEIVED_FRAME_IND: - frametype = fapi_get_u16(skb, u.mlme_received_frame_ind.data_unit_descriptor); - break; - case MLME_SCAN_IND: - frametype = FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME; - rssi = fapi_get_s16(skb, u.mlme_scan_ind.rssi); - vif = fapi_get_u16(skb, u.mlme_scan_ind.scan_id) >> 8; - break; - case MLME_CONNECT_CFM: - case MLME_CONNECT_IND: - case MLME_PROCEDURE_STARTED_IND: - case MLME_CONNECTED_IND: - case MLME_REASSOCIATE_IND: - case MLME_ROAMED_IND: - frametype = FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME; - break; - default: - return; - } - - switch (frametype) { - case FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME: - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)frame; - - dst = hdr->addr1; - src = hdr->addr2; - print = slsi_decode_80211_frame(frame, len, frame_info, sizeof(frame_info)); - break; - } - case FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME: - { - struct ethhdr *ehdr = (struct ethhdr *)frame; - - dst = ehdr->h_dest; - src = ehdr->h_source; - print = slsi_decode_l3_frame(frame, len, frame_info, sizeof(frame_info)); - break; - } - case FAPI_DATAUNITDESCRIPTOR_AMSDU_SUBFRAME: - { - struct ethhdr *ehdr = (struct ethhdr *)frame; - - dst = ehdr->h_dest; - src = ehdr->h_source; - print = slsi_decode_amsdu_subframe(frame, len, frame_info, sizeof(frame_info)); - break; - } - default: - return; - } - if (print) { -#ifdef CONFIG_SCSC_WLAN_SKB_TRACKING - SLSI_DBG4(sdev, SLSI_SUMMARY_FRAMES, "%-5s: 0x%p %s(vif:%u rssi:%-3d, s:%pM d:%pM)->%s\n", - dev ? netdev_name(dev) : "", skb, prefix, vif, rssi, src, dst, frame_info); -#else - SLSI_DBG4(sdev, SLSI_SUMMARY_FRAMES, "%-5s: %s(vif:%u rssi:%-3d, s:%pM d:%pM)->%s\n", - dev ? netdev_name(dev) : "", prefix, vif, rssi, src, dst, frame_info); -#endif - } -} - -#endif /* CONFIG_SCSC_WLAN_DEBUG */ diff --git a/drivers/net/wireless/scsc/dev.c b/drivers/net/wireless/scsc/dev.c deleted file mode 100755 index a4b5d04ef942..000000000000 --- a/drivers/net/wireless/scsc/dev.c +++ /dev/null @@ -1,599 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "dev.h" -#include "hip.h" -#include "mgt.h" -#include "debug.h" -#include "udi.h" -#include "hip_bh.h" -#include "cfg80211_ops.h" -#include "netif.h" -#include "procfs.h" -#include "ba.h" -#include "nl80211_vendor.h" - -#include "sap_mlme.h" -#include "sap_ma.h" -#include "sap_dbg.h" -#include "sap_test.h" - -#ifdef CONFIG_SCSC_WLAN_KIC_OPS -#include "kic.h" -#endif - -char *slsi_mib_file = "wlan.hcf"; -module_param_named(mib_file, slsi_mib_file, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mib_file, "mib data filename"); - -char *slsi_mib_file2 = "wlan_sw.hcf"; -module_param_named(mib_file2, slsi_mib_file2, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mib_file2, "sw mib data filename"); - -static char *local_mib_file = "localmib.hcf"; -module_param(local_mib_file, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(local_mib_file, "local mib data filename (Optional extra mib values)"); - -static char *maddr_file = "mac.txt"; -module_param(maddr_file, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(maddr_file, "mac address filename"); - -static bool term_udi_users = true; -module_param(term_udi_users, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(term_udi_users, "Try to terminate UDI user space users (applications) connected on the cdev (0, 1)"); - -static int sig_wait_cfm_timeout = 6000; -module_param(sig_wait_cfm_timeout, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(sig_wait_cfm_timeout, "Signal wait timeout in milliseconds (default: 3000)"); - -static bool lls_disabled; -module_param(lls_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(lls_disabled, "Disable LLS: to disable LLS set 1"); - -static bool gscan_disabled = 0; -module_param(gscan_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(gscan_disabled, "Disable gscan: to disable gscan set 1"); - -static bool llslogs_disabled; -module_param(llslogs_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(llslogs_disabled, "Disable llslogs: to disable llslogs set 1"); - -static bool epno_disabled; -module_param(epno_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(epno_disabled, "Disable ePNO: to disable ePNO set 1.\nNote: for ePNO to work gscan should be enabled"); - -static bool vo_vi_block_ack_disabled; -module_param(vo_vi_block_ack_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(vo_vi_block_ack_disabled, "Disable VO VI Block Ack logic added for WMM AC Cert : 5.1.4"); - -static int max_scan_result_count = 200; -module_param(max_scan_result_count, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(max_scan_result_count, "Max scan results to be reported"); -static bool rtt_disabled = 1; -module_param(rtt_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(rtt_disabled, "Disable rtt: to disable rtt set 1"); - -static bool nan_disabled; -module_param(nan_disabled, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(nan_disabled, "Disable NAN: to disable NAN set 1."); - -bool slsi_dev_gscan_supported(void) -{ - return !gscan_disabled; -} - -bool slsi_dev_rtt_supported(void) -{ - return !rtt_disabled; -} - -bool slsi_dev_llslogs_supported(void) -{ - return !llslogs_disabled; -} - -bool slsi_dev_lls_supported(void) -{ - return !lls_disabled; -} - -bool slsi_dev_epno_supported(void) -{ - return !epno_disabled; -} - -bool slsi_dev_vo_vi_block_ack(void) -{ - return vo_vi_block_ack_disabled; -} - -int slsi_dev_get_scan_result_count(void) -{ - return max_scan_result_count; -} - -int slsi_dev_nan_supported(struct slsi_dev *sdev) -{ -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - if (sdev) - return sdev->nan_enabled && !nan_disabled; - return false; -#else - return false; -#endif -} - -static int slsi_dev_inetaddr_changed(struct notifier_block *nb, unsigned long data, void *arg) -{ - struct slsi_dev *sdev = container_of(nb, struct slsi_dev, inetaddr_notifier); - struct in_ifaddr *ifa = arg; - struct net_device *dev = ifa->ifa_dev->dev; - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct netdev_vif *ndev_vif = netdev_priv(dev); - - if (!wdev) - return NOTIFY_DONE; - - if (wdev->wiphy != sdev->wiphy) - return NOTIFY_DONE; - - if (data == NETDEV_DOWN) { - SLSI_NET_DBG2(dev, SLSI_NETDEV, "Returning 0 for NETDEV_DOWN event\n"); - return 0; - } - - SLSI_NET_INFO(dev, "IP: %pI4\n", &ifa->ifa_address); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); -#if !defined SLSI_TEST_DEV && defined CONFIG_ANDROID - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif) && wake_lock_active(&sdev->wlan_wl_roam)) { - SLSI_NET_DBG2(dev, SLSI_NETDEV, "Releasing the roaming wakelock\n"); - wake_unlock(&sdev->wlan_wl_roam); - /* If upper layers included wps ie in connect but the actually - * connection is not for wps, reset the wps flag. - */ - if (ndev_vif->sta.is_wps) { - SLSI_NET_DBG1(dev, SLSI_NETDEV, - "is_wps set but not wps connection.\n"); - ndev_vif->sta.is_wps = false; - } - } -#endif - slsi_ip_address_changed(sdev, dev, ifa->ifa_address); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return 0; -} - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 -static int slsi_dev_inet6addr_changed(struct notifier_block *nb, unsigned long data, void *arg) -{ - struct slsi_dev *sdev = container_of(nb, struct slsi_dev, inet6addr_notifier); - struct inet6_ifaddr *ifa = arg; - struct net_device *dev = ifa->idev->dev; - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct netdev_vif *ndev_vif = netdev_priv(dev); - - (void)data; /* unused */ - - if (!wdev) - return NOTIFY_DONE; - - if (wdev->wiphy != sdev->wiphy) - return NOTIFY_DONE; - - SLSI_NET_INFO(dev, "IPv6: %pI6\n", &ifa->addr.s6_addr); - - slsi_spinlock_lock(&ndev_vif->ipv6addr_lock); - memcpy(&ndev_vif->ipv6address, &ifa->addr, sizeof(struct in6_addr)); - slsi_spinlock_unlock(&ndev_vif->ipv6addr_lock); - - return 0; -} -#endif - -void slsi_regd_init(struct slsi_dev *sdev) -{ - struct ieee80211_regdomain *slsi_world_regdom_custom = sdev->device_config.domain_info.regdomain; - struct ieee80211_reg_rule reg_rules[] = { - /* Channel 1 - 11*/ - REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0), -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - /* Channel 12 - 13 NO_IR*/ - REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20, NL80211_RRF_NO_IR), -#endif - /* Channel 36 - 48 */ - REG_RULE(5180 - 10, 5240 + 10, 80, 0, 20, 0), - /* Channel 52 - 64 */ - REG_RULE(5260 - 10, 5320 + 10, 80, 0, 20, NL80211_RRF_DFS), - /* Channel 100 - 140 */ - REG_RULE(5500 - 10, 5700 + 10, 80, 0, 20, NL80211_RRF_DFS), - /* Channel 149 - 165 */ - REG_RULE(5745 - 10, 5825 + 10, 80, 0, 20, 0), - }; - - int i; - - SLSI_DBG1_NODEV(SLSI_INIT_DEINIT, "regulatory init\n"); - slsi_world_regdom_custom->n_reg_rules = 6; - for (i = 0; i < slsi_world_regdom_custom->n_reg_rules; i++) - slsi_world_regdom_custom->reg_rules[i] = reg_rules[i]; - - /* Country code '00' indicates world regulatory domain */ - slsi_world_regdom_custom->alpha2[0] = '0'; - slsi_world_regdom_custom->alpha2[1] = '0'; - - wiphy_apply_custom_regulatory(sdev->wiphy, slsi_world_regdom_custom); -} - -struct slsi_dev *slsi_dev_attach(struct device *dev, struct scsc_mx *core, struct scsc_service_client *mx_wlan_client) -{ - struct slsi_dev *sdev; - int i; - - SLSI_DBG1_NODEV(SLSI_INIT_DEINIT, "Add Device\n"); - - sdev = slsi_cfg80211_new(dev); - if (!sdev) { - SLSI_ERR_NODEV("No sdev\n"); - return NULL; - } - - sdev->mlme_blocked = false; - - SLSI_MUTEX_INIT(sdev->netdev_add_remove_mutex); - mutex_init(&sdev->netdev_remove_mutex); - SLSI_MUTEX_INIT(sdev->start_stop_mutex); - SLSI_MUTEX_INIT(sdev->device_config_mutex); - SLSI_MUTEX_INIT(sdev->logger_mutex); - - sdev->dev = dev; - sdev->maxwell_core = core; - memcpy(&sdev->mx_wlan_client, mx_wlan_client, sizeof(struct scsc_service_client)); - - sdev->fail_reported = false; - sdev->p2p_certif = false; - sdev->allow_switch_40_mhz = true; - sdev->allow_switch_80_mhz = true; - sdev->mib[0].mib_file_name = slsi_mib_file; - sdev->mib[1].mib_file_name = slsi_mib_file2; - sdev->local_mib.mib_file_name = local_mib_file; - sdev->maddr_file_name = maddr_file; - sdev->device_config.qos_info = -1; - sdev->acs_channel_switched = false; - memset(&sdev->chip_info_mib, 0xFF, sizeof(struct slsi_chip_info_mib)); - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - sdev->num_5g_restricted_channels = 0; -#endif - -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - sdev->device_config.okc_mode = 0; - sdev->device_config.wes_mode = 0; - sdev->device_config.roam_scan_mode = 0; -#endif - - slsi_log_clients_init(sdev); - - slsi_wakelock_init(&sdev->wlan_wl, "wlan"); - slsi_wakelock_init(&sdev->wlan_wl_mlme, "wlan_mlme"); - slsi_wakelock_init(&sdev->wlan_wl_ma, "wlan_ma"); -#if !defined SLSI_TEST_DEV && defined CONFIG_ANDROID - wake_lock_init(&sdev->wlan_wl_roam, WAKE_LOCK_SUSPEND, "wlan_roam"); -#endif - sdev->recovery_next_state = 0; - init_completion(&sdev->recovery_remove_completion); - init_completion(&sdev->recovery_stop_completion); - init_completion(&sdev->recovery_completed); - sdev->recovery_status = 0; - - sdev->term_udi_users = &term_udi_users; - sdev->sig_wait_cfm_timeout = &sig_wait_cfm_timeout; - slsi_sig_send_init(&sdev->sig_wait); - - for (i = 0; i < SLSI_LLS_AC_MAX; i++) - atomic_set(&sdev->tx_host_tag[i], ((1 << 2) | i)); - - if (slsi_skb_work_init(sdev, NULL, &sdev->rx_dbg_sap, "slsi_wlan_rx_dbg_sap", slsi_rx_dbg_sap_work) != 0) - goto err_if; - - if (slsi_netif_init(sdev) != 0) { - SLSI_ERR(sdev, "Can not create the network interface\n"); - goto err_ctrl_wq_init; - } - - if (slsi_hip_init(sdev, dev) != 0) { - SLSI_ERR(sdev, "slsi_hip_init() Failed\n"); - goto err_netif_init; - } - - if (slsi_udi_node_init(sdev, dev) != 0) { - SLSI_ERR(sdev, "failed to init UDI\n"); - goto err_hip_init; - } - - slsi_create_proc_dir(sdev); - slsi_traffic_mon_clients_init(sdev); - - /* update regulatory domain */ - slsi_regd_init(sdev); - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - slsi_nl80211_vendor_init(sdev); -#endif - - if (slsi_cfg80211_register(sdev) != 0) { - SLSI_ERR(sdev, "failed to register with cfg80211\n"); - goto err_udi_proc_init; - } - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - sdev->inet6addr_notifier.notifier_call = slsi_dev_inet6addr_changed; - if (register_inet6addr_notifier(&sdev->inet6addr_notifier) != 0) { - SLSI_ERR(sdev, "failed to register inet6addr_notifier\n"); - goto err_cfg80211_registered; - } -#endif - - sdev->inetaddr_notifier.notifier_call = slsi_dev_inetaddr_changed; - if (register_inetaddr_notifier(&sdev->inetaddr_notifier) != 0) { - SLSI_ERR(sdev, "failed to register inetaddr_notifier\n"); -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - unregister_inet6addr_notifier(&sdev->inet6addr_notifier); -#endif - goto err_cfg80211_registered; - } - -#ifdef SLSI_TEST_DEV - slsi_init_netdev_mac_addr(sdev); -#endif - slsi_rx_ba_init(sdev); - - if (slsi_netif_register(sdev, sdev->netdev[SLSI_NET_INDEX_WLAN]) != 0) { - SLSI_ERR(sdev, "failed to register with wlan netdev\n"); - goto err_inetaddr_registered; - } -#ifdef CONFIG_SCSC_WLAN_STA_ONLY - SLSI_ERR(sdev, "CONFIG_SCSC_WLAN_STA_ONLY: not registering p2p netdev\n"); -#else - if (slsi_netif_register(sdev, sdev->netdev[SLSI_NET_INDEX_P2P]) != 0) { - SLSI_ERR(sdev, "failed to register with p2p netdev\n"); - goto err_wlan_registered; - } -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000) - if (slsi_netif_register(sdev, sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]) != 0) { - SLSI_ERR(sdev, "failed to register with p2px_wlan1 netdev\n"); - goto err_p2p_registered; - } - rcu_assign_pointer(sdev->netdev_ap, sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]); -#endif -#endif -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - if (slsi_netif_register(sdev, sdev->netdev[SLSI_NET_INDEX_NAN]) != 0) { - SLSI_ERR(sdev, "failed to register with NAN netdev\n"); -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000) - goto err_p2px_wlan_registered; -#else - goto err_p2p_registered; -#endif -#else - goto err_p2p_registered; -#endif - } -#endif -#endif -#ifdef CONFIG_SCSC_WLAN_KIC_OPS - if (wifi_kic_register(sdev) < 0) - SLSI_ERR(sdev, "failed to register Wi-Fi KIC ops\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - sdev->enhanced_pkt_filter_enabled = true; -#endif -#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER - sdev->abnormal_multicast_pkt_filter_enabled = true; -#endif - sdev->device_state = SLSI_DEVICE_STATE_STOPPED; - sdev->current_tspec_id = -1; - sdev->tspec_error_code = -1; - - /* Driver workqueue used to queue work in different modes (STA/P2P/HS2) */ - sdev->device_wq = alloc_ordered_workqueue("slsi_wlan_wq", 0); - if (!sdev->device_wq) { - SLSI_ERR(sdev, "Cannot allocate workqueue\n"); -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - goto err_nan_registered; -#else -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000) - goto err_p2px_wlan_registered; -#else - goto err_p2p_registered; -#endif -#else - goto err_p2p_registered; -#endif -#endif - } - return sdev; - -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 -err_nan_registered: - slsi_netif_remove(sdev, sdev->netdev[SLSI_NET_INDEX_NAN]); -#endif - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000) -err_p2px_wlan_registered: - slsi_netif_remove(sdev, sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]); - rcu_assign_pointer(sdev->netdev_ap, NULL); -#endif -#endif - -err_p2p_registered: - slsi_netif_remove(sdev, sdev->netdev[SLSI_NET_INDEX_P2P]); - -err_wlan_registered: - slsi_netif_remove(sdev, sdev->netdev[SLSI_NET_INDEX_WLAN]); - -err_inetaddr_registered: - unregister_inetaddr_notifier(&sdev->inetaddr_notifier); -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - unregister_inet6addr_notifier(&sdev->inet6addr_notifier); -#endif - -err_cfg80211_registered: - slsi_cfg80211_unregister(sdev); - -err_udi_proc_init: - slsi_traffic_mon_clients_deinit(sdev); - slsi_remove_proc_dir(sdev); - slsi_udi_node_deinit(sdev); - -err_hip_init: - slsi_hip_deinit(sdev); - -err_netif_init: - slsi_netif_deinit(sdev); - -err_ctrl_wq_init: - slsi_skb_work_deinit(&sdev->rx_dbg_sap); - -err_if: - slsi_wakelock_exit(&sdev->wlan_wl); - slsi_wakelock_exit(&sdev->wlan_wl_mlme); - slsi_wakelock_exit(&sdev->wlan_wl_ma); -#if !defined SLSI_TEST_DEV && defined CONFIG_ANDROID - wake_lock_destroy(&sdev->wlan_wl_roam); -#endif - slsi_cfg80211_free(sdev); - return NULL; -} - -void slsi_dev_detach(struct slsi_dev *sdev) -{ - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "Remove Device\n"); - - slsi_stop(sdev); - -#ifdef CONFIG_SCSC_WLAN_KIC_OPS - wifi_kic_unregister(); -#endif - complete_all(&sdev->sig_wait.completion); - complete_all(&sdev->recovery_remove_completion); - complete_all(&sdev->recovery_stop_completion); - complete_all(&sdev->recovery_completed); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Unregister inetaddr_notifier\n"); - unregister_inetaddr_notifier(&sdev->inetaddr_notifier); - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Unregister inet6addr_notifier\n"); - unregister_inet6addr_notifier(&sdev->inet6addr_notifier); -#endif - - WARN_ON(!sdev->device_wq); - if (sdev->device_wq) - flush_workqueue(sdev->device_wq); - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - slsi_nl80211_vendor_deinit(sdev); -#endif - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Unregister netif\n"); - slsi_netif_remove_all(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Unregister cfg80211\n"); - slsi_cfg80211_unregister(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Remove proc entries\n"); - slsi_remove_proc_dir(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "De-initialise the Traffic monitor\n"); - slsi_traffic_mon_clients_deinit(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "De-initialise the UDI\n"); - slsi_log_clients_terminate(sdev); - slsi_udi_node_deinit(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "De-initialise Hip\n"); - slsi_hip_deinit(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "De-initialise netif\n"); - slsi_netif_deinit(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "De-initialise Regulatory\n"); - slsi_regd_deinit(sdev); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Stop Work Queues\n"); - slsi_skb_work_deinit(&sdev->rx_dbg_sap); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Clean up wakelock\n"); - slsi_wakelock_exit(&sdev->wlan_wl); - slsi_wakelock_exit(&sdev->wlan_wl_mlme); - slsi_wakelock_exit(&sdev->wlan_wl_ma); -#if !defined SLSI_TEST_DEV && defined CONFIG_ANDROID - wake_lock_destroy(&sdev->wlan_wl_roam); -#endif - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Free cfg80211\n"); - slsi_cfg80211_free(sdev); - - slsi_dbg_track_skb_report(); - slsi_dbg_track_skb_reset(); -} - -int __init slsi_dev_load(void) -{ - SLSI_INFO_NODEV("Loading Maxwell Wi-Fi driver\n"); - - slsi_dbg_track_skb_init(); - - if (slsi_udi_init()) - SLSI_INFO_NODEV("Failed to init udi - continuing\n"); - - if (slsi_sm_service_driver_register()) - SLSI_INFO_NODEV("slsi_sm_service_driver_register failed - continuing\n"); - - /* Register SAPs */ - sap_mlme_init(); - sap_ma_init(); - sap_dbg_init(); - sap_test_init(); - -/* Always create devnode if TW Android P on */ -#if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000 - slsi_create_sysfs_macaddr(); -#endif - SLSI_INFO_NODEV("--- Maxwell Wi-Fi driver loaded successfully ---\n"); - return 0; -} - -void __exit slsi_dev_unload(void) -{ - SLSI_INFO_NODEV("Unloading Maxwell Wi-Fi driver\n"); - -#if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000 - slsi_destroy_sysfs_macaddr(); -#endif - /* Unregister SAPs */ - sap_mlme_deinit(); - sap_ma_deinit(); - sap_dbg_deinit(); - sap_test_deinit(); - - slsi_sm_service_driver_unregister(); - - slsi_udi_deinit(); - - SLSI_INFO_NODEV("--- Maxwell Wi-Fi driver unloaded successfully ---\n"); -} - -module_init(slsi_dev_load); -module_exit(slsi_dev_unload); - -MODULE_DESCRIPTION("mx140 Wi-Fi Driver"); -MODULE_AUTHOR("SLSI"); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/net/wireless/scsc/dev.h b/drivers/net/wireless/scsc/dev.h deleted file mode 100755 index e27645eb0f55..000000000000 --- a/drivers/net/wireless/scsc/dev.h +++ /dev/null @@ -1,1311 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_DEVICE_H__ -#define __SLSI_DEVICE_H__ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "fapi.h" -#include "const.h" -#include "utils.h" -#include "hip.h" -#include "log_clients.h" -#include "src_sink.h" -#include "scsc_wifi_fcq.h" -#include "scsc_wifi_cm_if.h" -#include "hip4.h" -#include "nl80211_vendor.h" -#include "traffic_monitor.h" - -#define FAPI_MAJOR_VERSION(v) (((v) >> 8) & 0xFF) -#define FAPI_MINOR_VERSION(v) ((v) & 0xFF) - -/* Modes for CMDGETBSSINFO and CMDGETSTAINFO */ -#define SLSI_80211_MODE_11B 0 -#define SLSI_80211_MODE_11G 1 -#define SLSI_80211_MODE_11N 2 -#define SLSI_80211_MODE_11A 3 -#define SLSI_80211_MODE_11AC 4 - -#define SLSI_FW_API_RATE_HT_SELECTOR_FIELD 0xc000 -#define SLSI_FW_API_RATE_NON_HT_SELECTED 0x4000 -#define SLSI_FW_API_RATE_HT_SELECTED 0x8000 -#define SLSI_FW_API_RATE_VHT_SELECTED 0xc000 - -#define SLSI_FW_API_RATE_VHT_MCS_FIELD 0x000F -#define SLSI_FW_API_RATE_HT_MCS_FIELD 0x003F -#define SLSI_FW_API_RATE_INDEX_FIELD 0x1fff -#define SLSI_FW_API_RATE_VHT_NSS_FIELD 0x0070 -#define SLSI_FW_API_RATE_HT_NSS_FIELD 0x0040 - -#define SLSI_FW_API_RATE_BW_FIELD 0x0600 -#define SLSI_FW_API_RATE_BW_40MHZ 0x0200 -#define SLSI_FW_API_RATE_BW_20MHZ 0x0000 - -#define SLSI_FW_API_RATE_SGI 0x0100 -#define SLSI_FW_API_RATE_GF 0x0080 - -#define SLSI_HOSTSTATE_LCD_ACTIVE 0x0001 -#define SLSI_HOSTSTATE_CELLULAR_ACTIVE 0x0002 -#define SLSI_HOSTSTATE_SAR_ACTIVE 0x0004 -#define SLSI_HOSTSTATE_GRIP_ACTIVE 0x0040 -#define SLSI_HOSTSTATE_LOW_LATENCY_ACTIVE 0x0080 - -/* indices: 3= BW20->idx_0, BW40->idx_1, BW80->idx_2. - * 2= noSGI->idx_0, SGI->idx_1 - * 10= mcs index - * rate units 100kbps - * This table for single stream Nss=1and does not include 160MHz BW and 80+80MHz BW. - */ -static const u16 slsi_rates_table[3][2][10] = { - { /* BW20 */ - { /* no SGI */ - 65, 130, 195, 260, 390, 520, 585, 650, 780, 0 - }, - { /* SGI */ - 72, 144, 217, 289, 433, 578, 650, 722, 867, 0 - } - }, - { /* BW40 */ - { /* no SGI */ - 135, 270, 405, 540, 810, 1080, 1215, 1350, 1620, 1800 - }, - { /* SGI */ - 150, 300, 450, 600, 900, 1200, 1350, 1500, 1800, 2000 - } - }, - { /* BW80 */ - { /* no SGI */ - 293, 585, 878, 1170, 1755, 2340, 2633, 2925, 3510, 3900 - }, - { /* SGI */ - 325, 650, 975, 1300, 1950, 2600, 2925, 3250, 3900, 4333 - } - } -}; -/* MSDU subframe Header */ -struct msduhdr { - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - __be16 len; /* MSDU Subframe length */ - unsigned char dsap; /* DSAP field - SNAP 0xaa */ - unsigned char ssap; /* SSAP field - SNAP 0xaa */ - unsigned char ui; /* Control field: U, func UI - 0x03 */ - unsigned char oui[3]; /* Organization Code - 0x000000 */ - __be16 type; /* Type - 0x0800 (IPv4)*/ -} __attribute__((packed)); - -static inline void ethr_ii_to_subframe_msdu(struct sk_buff *skb) -{ - struct ethhdr *ehdr; - struct msduhdr msduh; - - ehdr = eth_hdr(skb); - ether_addr_copy(msduh.h_dest, ehdr->h_dest); - ether_addr_copy(msduh.h_source, ehdr->h_source); - /* adjust packet length */ - msduh.len = cpu_to_be16(skb->len - 6); - msduh.dsap = 0xaa; - msduh.ssap = 0xaa; - msduh.ui = 0x03; - memset(msduh.oui, 0x0, 3); - msduh.type = ehdr->h_proto; - (void)skb_push(skb, sizeof(struct msduhdr) - sizeof(struct ethhdr)); - /* update SKB mac_header to point to start of MSDU header */ - skb->mac_header -= (sizeof(struct msduhdr) - sizeof(struct ethhdr)); - memcpy(skb->data, &msduh, sizeof(struct msduhdr)); -} - -#define SLSI_TX_PROCESS_ID_MIN (0xC001) -#define SLSI_TX_PROCESS_ID_MAX (0xCF00) -#define SLSI_TX_PROCESS_ID_UDI_MIN (0xCF01) -#define SLSI_TX_PROCESS_ID_UDI_MAX (0xCFFE) - -/* There are no wakelocks in kernel/supplicant/hostapd. - * So keep the platform active for some time after receiving any data packet. - * This timeout value can be fine-tuned based on the test results. - */ -#define SLSI_RX_WAKELOCK_TIME (200) -#define MAX_BA_BUFFER_SIZE 64 -#define NUM_BA_SESSIONS_PER_PEER 8 -#define MAX_CHANNEL_LIST 20 -#define SLSI_MAX_RX_BA_SESSIONS (8) -#define SLSI_STA_ACTION_FRAME_BITMAP (SLSI_ACTION_FRAME_PUBLIC | SLSI_ACTION_FRAME_WMM | SLSI_ACTION_FRAME_WNM |\ - SLSI_ACTION_FRAME_QOS | SLSI_ACTION_FRAME_PROTECTED_DUAL |\ - SLSI_ACTION_FRAME_RADIO_MEASUREMENT) - -/* Default value for MIB SLSI_PSID_UNIFI_DISCONNECT_TIMEOUT + 1 sec*/ -#define SLSI_DEFAULT_AP_DISCONNECT_IND_TIMEOUT 3000 - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) -#define WLAN_EID_VHT_CAPABILITY 191 -#define WLAN_EID_VHT_OPERATION 192 -#endif - -#define NUM_COUNTRY (300) - -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG -#define SLSI_MUTEX_INIT(slsi_mutex__) \ - { \ - (slsi_mutex__).owner = NULL; \ - mutex_init(&(slsi_mutex__).mutex); \ - (slsi_mutex__).valid = true; \ - } - -#define SLSI_MUTEX_LOCK(slsi_mutex_to_lock) \ - { \ - (slsi_mutex_to_lock).line_no_before = __LINE__; \ - (slsi_mutex_to_lock).file_name_before = __FILE__; \ - mutex_lock(&(slsi_mutex_to_lock).mutex); \ - (slsi_mutex_to_lock).owner = current; \ - (slsi_mutex_to_lock).line_no_after = __LINE__; \ - (slsi_mutex_to_lock).file_name_after = __FILE__; \ - (slsi_mutex_to_lock).function = __func__; \ - } - -#define SLSI_MUTEX_UNLOCK(slsi_mutex_to_unlock) \ - { \ - (slsi_mutex_to_unlock).owner = NULL; \ - mutex_unlock(&(slsi_mutex_to_unlock).mutex); \ - } -#define SLSI_MUTEX_IS_LOCKED(slsi_mutex__) mutex_is_locked(&(slsi_mutex__).mutex) - -struct slsi_mutex { - bool valid; - u32 line_no_before; - const u8 *file_name_before; - /* a std mutex */ - struct mutex mutex; - u32 line_no_after; - const u8 *file_name_after; - const u8 *function; - struct task_struct *owner; -}; - -#else -#define SLSI_MUTEX_INIT(mutex__) mutex_init(&(mutex__)) -#define SLSI_MUTEX_LOCK(mutex_to_lock) mutex_lock(&(mutex_to_lock)) -#define SLSI_MUTEX_UNLOCK(mutex_to_unlock) mutex_unlock(&(mutex_to_unlock)) -#define SLSI_MUTEX_IS_LOCKED(mutex__) mutex_is_locked(&(mutex__)) -#endif - -#define OS_UNUSED_PARAMETER(x) ((void)(x)) - -#define SLSI_HOST_TAG_TRAFFIC_QUEUE(htag) (htag & 0x00000003) - -/* For each mlme-req a mlme-cfm is expected to be received from the - * firmware. The host is not allowed to send another mlme-req until - * the mlme-cfm is received. - * - * However there are also instances where we need to wait for an mlme-ind - * following a mlme-req/cfm exchange. One example of this is the disconnect - * sequence: - * mlme-disconnect-req - host requests disconnection - * mlme-disconnect-cfm - firmware accepts disconnection request but hasn't - * disconnected yet. - * mlme-disconnect-ind - firmware reports final result of disconnection - * - * Assuming that waiting for the mlme-ind following on from the mlme-req/cfm - * is ok. - */ -struct slsi_sig_send { - /* a std spinlock */ - spinlock_t send_signal_lock; -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - struct slsi_mutex mutex; -#else - /* a std mutex */ - struct mutex mutex; -#endif - struct completion completion; - - u16 process_id; - u16 req_id; - u16 cfm_id; - u16 ind_id; - struct sk_buff *cfm; - struct sk_buff *ind; - struct sk_buff *mib_error; -}; - -static inline void slsi_sig_send_init(struct slsi_sig_send *sig_send) -{ - spin_lock_init(&sig_send->send_signal_lock); - sig_send->req_id = 0; - sig_send->cfm_id = 0; - sig_send->process_id = SLSI_TX_PROCESS_ID_MIN; - SLSI_MUTEX_INIT(sig_send->mutex); - init_completion(&sig_send->completion); -} - -struct slsi_ba_frame_desc { - bool active; - struct sk_buff *signal; - u16 sn; -}; - -struct slsi_ba_session_rx { - bool active; - bool used; - void *vif; - struct slsi_ba_frame_desc buffer[MAX_BA_BUFFER_SIZE]; - u16 buffer_size; - u16 occupied_slots; - u16 expected_sn; - u16 start_sn; - u16 highest_received_sn; - bool trigger_ba_after_ssn; - u8 tid; - - /* Aging timer parameters */ - bool timer_on; - struct timer_list ba_age_timer; - struct slsi_spinlock ba_lock; - struct net_device *dev; -}; - -#define SLSI_TID_MAX (16) -#define SLSI_AMPDU_F_INITIATED (0x0001) -#define SLSI_AMPDU_F_CREATED (0x0002) -#define SLSI_AMPDU_F_OPERATIONAL (0x0004) - -#define SLSI_SCAN_HW_ID 0 -#define SLSI_SCAN_SCHED_ID 1 -#define SLSI_SCAN_MAX 3 - -#define SLSI_SCAN_SSID_MAP_MAX 10 /* Arbitrary value */ -#define SLSI_SCAN_SSID_MAP_EXPIRY_AGE 2 /* If hidden bss not found these many scan cycles, remove map. Arbitrary value*/ -#define SLSI_FW_SCAN_DONE_TIMEOUT_MSEC (15 * 1000) - -struct slsi_scan_result { - u8 bssid[ETH_ALEN]; - u8 hidden; - int rssi; - struct sk_buff *probe_resp; - struct sk_buff *beacon; - struct slsi_scan_result *next; - int band; -}; - -/* Per Interface Scan Data - * Access protected by: cfg80211_lock - */ -struct slsi_scan { - /* When a Scan is running this not NULL. */ - struct cfg80211_scan_request *scan_req; - struct slsi_acs_request *acs_request; - struct cfg80211_sched_scan_request *sched_req; - bool requeue_timeout_work; - - /* Indicates if the scan req is blocking. i.e, waiting until scan_done_ind received */ - bool is_blocking_scan; - - struct slsi_scan_result *scan_results; /* head for scan_results list*/ -}; - -struct slsi_ssid_map { - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - u8 ssid_len; - u8 age; - int band; -}; - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -struct slsi_enhanced_arp_counters { - u16 arp_req_count_from_netdev; - u16 arp_req_count_to_lower_mac; - u16 arp_req_rx_count_by_lower_mac; - u16 arp_req_count_tx_success; - u16 arp_rsp_rx_count_by_lower_mac; - u16 arp_rsp_rx_count_by_upper_mac; - u16 arp_rsp_count_to_netdev; - u16 arp_rsp_count_out_of_order_drop; - u16 ap_link_active; - bool is_duplicate_addr_detected; -}; -#endif - -struct slsi_peer { - /* Flag MUST be set last when creating a record and immediately when removing. - * Otherwise another process could test the flag and start using the data. - */ - bool valid; - u8 address[ETH_ALEN]; - - /* Presently connected_state is used only for AP/GO mode*/ - u8 connected_state; - u16 aid; - /* Presently is_wps is used only in P2P GO mode */ - bool is_wps; - u16 capabilities; - bool qos_enabled; - u8 queueset; - struct scsc_wifi_fcq_data_qset data_qs; - struct scsc_wifi_fcq_ctrl_q ctrl_q; - - bool authorized; - bool pairwise_key_set; - - /* Needed for STA/AP VIF */ - struct sk_buff *assoc_ie; - struct sk_buff_head buffered_frames; - /* Needed for STA VIF */ - struct sk_buff *assoc_resp_ie; - - /* bitmask that keeps the status of acm bit for each AC - * bit 7 6 5 4 3 2 1 0 - * | | | | | | | | - * vo vo vi vi be bk bk be - */ - u8 wmm_acm; - /* bitmask that keeps the status of tspec establishment for each priority - * bit 7 6 5 4 3 2 1 0 - * | | | | | | | | - * p7 p6 p5 p4 p3 p2 p1 p0 - */ - u8 tspec_established; - u8 uapsd; - - /* TODO_HARDMAC: - * Q: Can we obtain stats from the firmware? - * Yes - then this is NOT needed and we can just get from the firmware when requested. - * No - How much can we get from the PSCHED? - */ - struct station_info sinfo; - /* rate limit for peer sinfo mib reads */ - struct ratelimit_state sinfo_mib_get_rs; - struct slsi_ba_session_rx *ba_session_rx[NUM_BA_SESSIONS_PER_PEER]; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - /* qos map configured at peer end*/ - bool qos_map_set; - struct cfg80211_qos_map qos_map; -#endif -}; - -/* Used to update vif type on vif deactivation indicating vif is no longer available */ -#define SLSI_VIFTYPE_UNSPECIFIED 0xFFFF - -struct slsi_vif_mgmt_tx { - u64 cookie; /* Cookie assigned by Host for the tx mgmt frame */ - u16 host_tag; /* Host tag for the tx mgmt frame */ - const u8 *buf; /* Buffer - Mgmt frame requested for tx */ - size_t buf_len; /* Buffer length */ - u8 exp_frame; /* Next expected Public action frame subtype from peer */ -}; - -struct slsi_wmm_ac { - u8 aci_aifsn; - u8 ecw; - u16 txop_limit; -} __packed; - -/* struct slsi_wmm_parameter_element - * - * eid - Vendor Specific - * len - Remaining Length of IE - * oui - Microsoft OUI - * oui_type - WMM - * oui_subtype - Param IE - * version - 1 - * qos_info - Qos - * reserved - - * ac - BE,BK,VI,VO - */ -struct slsi_wmm_parameter_element { - u8 eid; - u8 len; - u8 oui[3]; - u8 oui_type; - u8 oui_subtype; - u8 version; - u8 qos_info; - u8 reserved; - struct slsi_wmm_ac ac[4]; -} __packed; - -#define SLSI_MIN_FILTER_ID 0x80 /* Start of filter range reserved for host */ - -/* for AP */ -#define SLSI_AP_ALL_IPV6_PKTS_FILTER_ID 0x80 - -/* filter IDs for filters installed by driver */ -#ifdef CONFIG_SCSC_WLAN_BLOCK_IPV6 - -enum slsi_filter_id { - SLSI_ALL_ARP_FILTER_ID = SLSI_MIN_FILTER_ID, /* 0x80 */ - SLSI_LOCAL_ARP_FILTER_ID, /* 0x81 */ - SLSI_ALL_BC_MC_FILTER_ID, /* 0x82 */ - SLSI_PROXY_ARP_FILTER_ID, /* 0x83 */ - SLSI_ALL_IPV6_PKTS_FILTER_ID, /* 0x84 */ -#ifndef CONFIG_SCSC_WLAN_DISABLE_NAT_KA - SLSI_NAT_IPSEC_FILTER_ID, /* 0x85 */ -#endif -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - SLSI_OPT_OUT_ALL_FILTER_ID, /* 0x86 */ - SLSI_OPT_IN_TCP4_FILTER_ID, /* 0x87 */ - SLSI_OPT_IN_TCP6_FILTER_ID, /* 0x88 */ -#endif - SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, /* 0x89 */ - SLSI_REGD_MC_FILTER_ID, /* 0x8A */ -}; -#else - -/* for STA */ -enum slsi_filter_id { - SLSI_ALL_ARP_FILTER_ID = SLSI_MIN_FILTER_ID, /* 0x80 */ - SLSI_LOCAL_ARP_FILTER_ID, /* 0x81 */ - SLSI_ALL_BC_MC_FILTER_ID, /* 0x82 */ - SLSI_PROXY_ARP_FILTER_ID, /* 0x83 */ - SLSI_LOCAL_NS_FILTER_ID, /* 0x84 */ - SLSI_PROXY_ARP_NA_FILTER_ID, /* 0x85 */ -#ifndef CONFIG_SCSC_WLAN_DISABLE_NAT_KA - SLSI_NAT_IPSEC_FILTER_ID, /* 0x86 */ -#endif -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - SLSI_OPT_OUT_ALL_FILTER_ID, /* 0x87 */ - SLSI_OPT_IN_TCP4_FILTER_ID, /* 0x88 */ - SLSI_OPT_IN_TCP6_FILTER_ID, /* 0x89 */ -#endif - SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, /* 0x8a */ - SLSI_REGD_MC_FILTER_ID, /* 0x8b */ -}; - -#endif - -#define SLSI_MAX_PKT_FILTERS 16 - -#ifndef CONFIG_SCSC_WLAN_DISABLE_NAT_KA -/* default config */ -#define SLSI_MC_ADDR_ENTRY_MAX (SLSI_MIN_FILTER_ID + SLSI_MAX_PKT_FILTERS - SLSI_REGD_MC_FILTER_ID) -#else -#define SLSI_MC_ADDR_ENTRY_MAX (SLSI_MIN_FILTER_ID + SLSI_MAX_PKT_FILTERS - SLSI_REGD_MC_FILTER_ID + 1) -#endif - -/* Values for vif_status field - * - * Used to indicate the status of an activated VIF, to help resolve - * conflicting activities with indications from the firmware eg. - * cfg80211 triggers a disconnection before a STA completes its - * connection to an AP. - */ -#define SLSI_VIF_STATUS_UNSPECIFIED 0 -#define SLSI_VIF_STATUS_CONNECTING 1 -#define SLSI_VIF_STATUS_CONNECTED 2 -#define SLSI_VIF_STATUS_DISCONNECTING 3 - -/*From wifi_offload.h (N_AVAIL_ID=3)*/ -#define SLSI_MAX_KEEPALIVE_ID 3 - -struct slsi_last_connected_bss { - u8 address[ETH_ALEN]; - int antenna_mode; - int rssi; - int mode; - int passpoint_version; - int snr; - int noise_level; - u16 bandwidth; - u16 roaming_count; - u16 channel_freq; - u16 tx_data_rate; - u8 roaming_akm; - u8 kv; - u32 kvie; - bool mimo_used; -}; - -struct slsi_vif_sta { - /* Only valid when the VIF is activated */ - u8 vif_status; - bool is_wps; - u16 eap_hosttag; - u16 m4_host_tag; - u16 keepalive_host_tag[SLSI_MAX_KEEPALIVE_ID]; - - struct sk_buff *roam_mlme_procedure_started_ind; - - /* This id is used to find out which response (connect resp/roamed resp/reassoc resp) - * is to be sent once M4 is transmitted successfully - */ - u16 resp_id; - bool gratuitous_arp_needed; - - /* regd multicast address*/ - u8 regd_mc_addr_count; - u8 regd_mc_addr[SLSI_MC_ADDR_ENTRY_MAX][ETH_ALEN]; - bool group_key_set; - struct sk_buff *mlme_scan_ind_skb; - bool roam_in_progress; - int tdls_peer_sta_records; - bool tdls_enabled; - struct cfg80211_bss *sta_bss; - u8 *assoc_req_add_info_elem; - u8 assoc_req_add_info_elem_len; - - /* List of seen ESS and Freq associated with them */ - struct list_head network_map; - - struct slsi_wmm_ac wmm_ac[4]; - bool nd_offload_enabled; - unsigned long data_rate_mbps; - unsigned long max_rate_mbps; - - /*This structure is used to store last disconnected bss info and valid even when vif is deactivated. */ - struct slsi_last_connected_bss last_connected_bss; - struct cfg80211_crypto_settings crypto; - - /* Variable to indicate if roamed_ind needs to be dropped in driver, to maintain roam synchronization. */ - atomic_t drop_roamed_ind; - u8 *vendor_disconnect_ies; - int vendor_disconnect_ies_len; -}; - -struct slsi_vif_unsync { - struct delayed_work roc_expiry_work; /* Work on ROC duration expiry */ - struct delayed_work del_vif_work; /* Work on unsync vif retention timeout */ - struct delayed_work hs2_del_vif_work; /* Work on HS2 unsync vif retention timeout */ - struct delayed_work unset_channel_expiry_work; /*unset channel after a timer */ - u64 roc_cookie; /* Cookie id for ROC */ - u8 *probe_rsp_ies; /* Probe response IEs to be configured in firmware */ - size_t probe_rsp_ies_len; /* Probe response IE length */ - bool ies_changed; /* To indicate if Probe Response IEs have changed from that previously stored */ - bool listen_offload; /* To indicate if Listen Offload is started */ - bool slsi_p2p_continuous_fullscan; -}; - -struct slsi_last_disconnected_sta { - u8 address[ETH_ALEN]; - u32 rx_retry_packets; - u32 rx_bc_mc_packets; - u16 capabilities; - int bandwidth; - int antenna_mode; - int rssi; - int mode; - u16 tx_data_rate; - bool mimo_used; - u16 reason; - int support_mode; -}; - -struct slsi_vif_ap { - struct slsi_wmm_parameter_element wmm_ie; - struct slsi_last_disconnected_sta last_disconnected_sta; - u8 *cache_wmm_ie; - u8 *cache_wpa_ie; - u8 *add_info_ies; - size_t wmm_ie_len; - size_t wpa_ie_len; - size_t add_info_ies_len; - bool p2p_gc_keys_set; /* Used in GO mode to identify that a CLI has connected after WPA2 handshake */ - bool privacy; /* Used for port enabling based on the open/secured AP configuration */ - bool qos_enabled; - int beacon_interval; /* Beacon interval in AP/GO mode */ - int mode; - bool non_ht_bss_present; /* Non HT BSS observed in HT20 OBSS scan */ - struct scsc_wifi_fcq_data_qset group_data_qs; - u32 cipher; - u16 channel_freq; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; -}; - -#define SLSI_NAN_MAX_PUBLISH_ID 16 -#define SLSI_NAN_MAX_SUBSCRIBE_ID 16 - -struct slsi_vif_nan { - u32 publish_id_map; - u32 subscribe_id_map; -}; - -#define TCP_ACK_SUPPRESSION_RECORDS_MAX 16 -#define TCP_ACK_SUPPRESSION_RECORD_UNUSED_TIMEOUT 10 /* in seconds */ - -#define TCP_ACK_SUPPRESSION_OPTIONS_OFFSET 20 -#define TCP_ACK_SUPPRESSION_OPTION_EOL 0 -#define TCP_ACK_SUPPRESSION_OPTION_NOP 1 -#define TCP_ACK_SUPPRESSION_OPTION_MSS 2 -#define TCP_ACK_SUPPRESSION_OPTION_WINDOW 3 -#define TCP_ACK_SUPPRESSION_OPTION_SACK 5 - -#define SLSI_IS_VIF_CHANNEL_5G(ndev_vif) (((ndev_vif)->chan) ? ((ndev_vif)->chan->hw_value > 14) : 0) - -struct slsi_tcp_ack_s { - u32 daddr; - u32 dport; - u32 saddr; - u32 sport; - struct sk_buff_head list; - u8 window_multiplier; - u16 mss; - u32 ack_seq; - u16 slow_start_count; - u8 count; - u8 max; - u8 age; - struct timer_list timer; - struct slsi_spinlock lock; - bool state; - ktime_t last_sent; - bool tcp_slow_start; - - /* TCP session throughput monitor */ - u16 hysteresis; - u32 last_tcp_rate; - ktime_t last_sample_time; - u32 last_ack_seq; - u64 num_bytes; -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - u8 stream_id; - u8 rx_window_scale; -#endif -}; - -struct slsi_tcp_ack_stats { - u32 tack_acks; - u32 tack_suppressed; - u32 tack_sent; - u32 tack_max; - u32 tack_timeout; - u32 tack_dacks; - u32 tack_sacks; - u32 tack_delay_acks; - u32 tack_low_window; - u32 tack_nocache; - u32 tack_norecord; - u32 tack_hasdata; - u32 tack_psh; - u32 tack_dropped; - u32 tack_ktime; - u32 tack_lastrecord; - u32 tack_searchrecord; - u32 tack_ece; -}; - -struct netdev_vif { - struct slsi_dev *sdev; - struct wireless_dev wdev; - atomic_t is_registered; /* Has the net dev been registered */ - bool is_available; /* Has the net dev been opened AND is usable */ - bool is_fw_test; /* Is the device in use as a test device via UDI */ -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - bool is_wips_running; -#endif - /* Structure can be accessed by cfg80211 ops, procfs/ioctls and as a result - * of receiving MLME indications e.g. MLME-CONNECT-IND that can affect the - * status of the interface eg. STA connect failure will delete the VIF. - */ -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - struct slsi_mutex vif_mutex; -#else - /* a std mutex */ - struct mutex vif_mutex; -#endif - struct slsi_sig_send sig_wait; - - struct slsi_skb_work rx_data; - struct slsi_skb_work rx_mlme; - u16 ifnum; - enum nl80211_iftype iftype; - enum nl80211_channel_type channel_type; - struct ieee80211_channel *chan; - u16 driver_channel; - bool drv_in_p2p_procedure; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - struct cfg80211_chan_def *chandef; -#endif - - /* NOTE: The Address is a __be32 - * It needs converting to pass to the FW - * But not for the Arp or trace %pI4 - */ - __be32 ipaddress; - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - struct in6_addr ipv6address; - struct slsi_spinlock ipv6addr_lock; -#endif - struct net_device_stats stats; - u32 rx_packets[SLSI_LLS_AC_MAX]; - u32 tx_packets[SLSI_LLS_AC_MAX]; - u32 tx_no_ack[SLSI_LLS_AC_MAX]; -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - struct slsi_mutex scan_mutex; - struct slsi_mutex scan_result_mutex; -#else - /* a std mutex */ - struct mutex scan_mutex; - struct mutex scan_result_mutex; - -#endif - struct slsi_scan scan[SLSI_SCAN_MAX]; - - struct slsi_src_sink_params src_sink_params; - u16 power_mode; - u16 set_power_mode; - - bool activated; /* VIF is created in firmware and ready to use */ - u16 vif_type; - struct slsi_spinlock peer_lock; - int peer_sta_records; - struct slsi_peer *peer_sta_record[SLSI_ADHOC_PEER_CONNECTIONS_MAX]; - - /* Used to populate the cfg80211 station_info structure generation variable. - * This number should increase every time the list of stations changes - * i.e. when a station is added or removed, so that userspace can tell - * whether it got a consistent snapshot. - */ - int cfg80211_sinfo_generation; - - /* Block Ack MPDU Re-order */ - struct sk_buff_head ba_complete; - atomic_t ba_flush; - - u64 mgmt_tx_cookie; /* Cookie id for mgmt tx */ - struct slsi_vif_mgmt_tx mgmt_tx_data; - struct delayed_work scan_timeout_work; /* Work on scan timeout */ - bool delete_probe_req_ies; /* Delete probe request stored at probe_req_ies, if - * connected for WAP2 at mlme_del_vif or in all cases - * if STA - */ - u8 *probe_req_ies; - size_t probe_req_ie_len; - - struct slsi_vif_unsync unsync; - struct slsi_vif_sta sta; - struct slsi_vif_ap ap; - struct slsi_vif_nan nan; - - /* TCP ack suppression. */ - struct slsi_tcp_ack_s *last_tcp_ack; - struct slsi_tcp_ack_s ack_suppression[TCP_ACK_SUPPRESSION_RECORDS_MAX]; - struct slsi_tcp_ack_stats tcp_ack_stats; - /* traffic monitor */ - ktime_t last_timer_time; - u32 report_time; - u32 num_bytes_tx_per_timer; - u32 num_bytes_rx_per_timer; - u32 num_bytes_tx_per_sec; - u32 num_bytes_rx_per_sec; - u32 throughput_tx; - u32 throughput_rx; - u32 throughput_tx_bps; - u32 throughput_rx_bps; -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - bool enhanced_arp_detect_enabled; - struct slsi_enhanced_arp_counters enhanced_arp_stats; - u8 target_ip_addr[4]; - int enhanced_arp_host_tag[5]; -#endif -}; - -struct slsi_802_11d_reg_domain { - u8 *countrylist; - struct ieee80211_regdomain *regdomain; - int country_len; -}; - -struct slsi_apf_capabilities { - u16 version; - u16 max_length; -}; - -#ifdef CONFIG_SCSC_WLAN_WES_NCHO -struct slsi_wes_mode_roam_scan_channels { - int n; - u8 channels[MAX_CHANNEL_LIST]; -}; -#endif - -struct slsi_dev_config { - /* Supported Freq Band (Dynamic) - * Set via the freq_band procfs - */ -#define SLSI_FREQ_BAND_AUTO 0 -#define SLSI_FREQ_BAND_5GHZ 1 -#define SLSI_FREQ_BAND_2GHZ 2 - int supported_band; - - struct ieee80211_supported_band *band_5G; - struct ieee80211_supported_band *band_2G; - - /* current user suspend mode - * Set via the suspend_mode procfs - * 0 : not suspended - * 1 : suspended - */ - int user_suspend_mode; - - /* Rx filtering rule - * Set via the rx_filter_num procfs - * 0: Unicast, 1: Broadcast, 2:Multicast IPv4, 3: Multicast IPv6 - */ - int rx_filter_num; - - /* Rx filter rule enabled - * Set via the rx_filter_start & rx_filter_stop procfs - */ - bool rx_filter_rule_started; - - /* AP Auto channel Selection */ -#define SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX 14 - int ap_auto_chan; - - /*QoS capability for a non-AP Station*/ - int qos_info; -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - /* NCHO OKC mode */ - int okc_mode; - - /*NCHO WES mode */ - int wes_mode; - - int roam_scan_mode; - - /*WES mode roam scan channels*/ - struct slsi_wes_mode_roam_scan_channels wes_roam_scan_list; -#endif - struct slsi_802_11d_reg_domain domain_info; - - int ap_disconnect_ind_timeout; - - u8 host_state; - - int rssi_boost_5g; - int rssi_boost_2g; - bool disable_ch12_ch13; - bool fw_enhanced_arp_detect_supported; - bool fw_apf_supported; - struct slsi_apf_capabilities apf_cap; -}; - -#define SLSI_DEVICE_STATE_ATTACHING 0 -#define SLSI_DEVICE_STATE_STOPPED 1 -#define SLSI_DEVICE_STATE_STARTING 2 -#define SLSI_DEVICE_STATE_STARTED 3 -#define SLSI_DEVICE_STATE_STOPPING 4 - -#define SLSI_NET_INDEX_WLAN 1 -#define SLSI_NET_INDEX_P2P 2 -#define SLSI_NET_INDEX_P2PX_SWLAN 3 -#define SLSI_NET_INDEX_NAN 4 - -/* States used during P2P operations */ -enum slsi_p2p_states { - P2P_IDLE_NO_VIF, /* Initial state - Unsync vif is not present */ - P2P_IDLE_VIF_ACTIVE, /* Unsync vif is present but no P2P procedure in progress */ - P2P_SCANNING, /* P2P SOCIAL channel (1,6,11) scan in progress. Not used for P2P full scan */ - P2P_LISTENING, /* P2P Listen (ROC) in progress */ - P2P_ACTION_FRAME_TX_RX, /* P2P Action frame Tx in progress or waiting for a peer action frame Rx (i.e. in response to the Tx frame) */ - P2P_GROUP_FORMED_CLI, /* P2P Group Formed - CLI role */ - P2P_GROUP_FORMED_GO, /* P2P Group Formed - GO role */ - /* NOTE: In P2P_LISTENING state if frame transmission is requested to driver then a peer response is ideally NOT expected. - * This is an assumption based on the fact that FIND would be stopped prior to group formation/connection. - * If driver were to receive a peer frame in P2P_LISTENING state then it would most probably be a REQUEST frame and the supplicant would respond to it. - * Hence the driver should get only RESPONSE frames for transmission in P2P_LISTENING state. - */ -}; - -enum slsi_wlan_state { - WLAN_UNSYNC_NO_VIF = 0, /* Initial state - Unsync vif is not present */ - WLAN_UNSYNC_VIF_ACTIVE, /* Unsync vif is activated but no wlan procedure in progress */ - WLAN_UNSYNC_VIF_TX /* Unsync vif is activated and wlan procedure in progress */ -}; - -/* Wakelock timeouts */ -#define SLSI_WAKELOCK_TIME_MSEC_EAPOL (1000) - -struct slsi_chip_info_mib { - u16 chip_version; -}; - -struct slsi_plat_info_mib { - u16 plat_build; -}; - -/* P2P States in text format for debug purposes */ -static inline char *slsi_p2p_state_text(u8 state) -{ - switch (state) { - case P2P_IDLE_NO_VIF: - return "P2P_IDLE_NO_VIF"; - case P2P_IDLE_VIF_ACTIVE: - return "P2P_IDLE_VIF_ACTIVE"; - case P2P_SCANNING: - return "P2P_SCANNING"; - case P2P_LISTENING: - return "P2P_LISTENING"; - case P2P_ACTION_FRAME_TX_RX: - return "P2P_ACTION_FRAME_TX_RX"; - case P2P_GROUP_FORMED_CLI: - return "P2P_GROUP_FORMED_CLI"; - case P2P_GROUP_FORMED_GO: - return "P2P_GROUP_FORMED_GO"; - default: - return "UNKNOWN"; - } -} - -#define SLSI_WLAN_MAX_HCF_PLATFORM_LEN (128) - -struct slsi_dev_mib_info { - char *mib_file_name; - unsigned int mib_hash; - - /* Cached File MIB Configuration values from User Space */ - u8 *mib_data; - u32 mib_len; - char platform[SLSI_WLAN_MAX_HCF_PLATFORM_LEN]; -}; - -#define SLSI_WLAN_MAX_MIB_FILE 2 /* Number of WLAN HCFs to load */ - -#ifdef CONFIG_SCSC_LOG_COLLECTION -struct slsi_dev_mib_collect_file { - char file_name[32]; - u16 len; - u8 *data; -} __packed; - -struct slsi_dev_mib_collect { - bool enabled; - /* Serialize writers/readers */ - spinlock_t in_collection; - char num_files; - /* +1 represents local_mib */ - struct slsi_dev_mib_collect_file file[SLSI_WLAN_MAX_MIB_FILE + 1]; -}; - -#endif - -struct slsi_dev { - /* Devices */ - struct device *dev; - struct wiphy *wiphy; - - struct slsi_hip hip; /* HIP bookkeeping block */ - struct slsi_hip4 hip4_inst; /* The handler to parse to HIP */ - - struct scsc_wifi_cm_if cm_if; /* cm_if bookkeeping block */ - struct scsc_mx *maxwell_core; - struct scsc_service_client mx_wlan_client; - struct scsc_service *service; - struct slsi_chip_info_mib chip_info_mib; - struct slsi_plat_info_mib plat_info_mib; - u16 reg_dom_version; - -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - struct slsi_mutex netdev_add_remove_mutex; -#else - /* a std mutex */ - struct mutex netdev_add_remove_mutex; -#endif - /* mutex to protect dynamic netdev removal */ - struct mutex netdev_remove_mutex; - int netdev_up_count; - struct net_device __rcu *netdev[CONFIG_SCSC_WLAN_MAX_INTERFACES + 1]; /* 0 is reserved */ - struct net_device __rcu *netdev_ap; - u8 netdev_addresses[CONFIG_SCSC_WLAN_MAX_INTERFACES + 1][ETH_ALEN]; /* 0 is reserved */ - - int device_state; - - /* BoT */ - atomic_t in_pause_state; - - /* Locking used to control Starting and stopping the chip */ -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - struct slsi_mutex start_stop_mutex; -#else - /* a std mutex */ - struct mutex start_stop_mutex; -#endif - /* UDI Logging */ - struct slsi_log_clients log_clients; - void *uf_cdev; - - /* ProcFS */ - int procfs_instance; - struct proc_dir_entry *procfs_dir; - - /* Configuration */ - u8 hw_addr[ETH_ALEN]; - struct slsi_dev_mib_info mib[SLSI_WLAN_MAX_MIB_FILE]; - struct slsi_dev_mib_info local_mib; -#ifdef CONFIG_SCSC_LOG_COLLECTION - struct slsi_dev_mib_collect collect_mib; -#endif - char *maddr_file_name; - bool *term_udi_users; /* Try to terminate UDI users during unload */ - int *sig_wait_cfm_timeout; - - struct slsi_wake_lock wlan_wl; - struct slsi_wake_lock wlan_wl_mlme; - struct slsi_wake_lock wlan_wl_ma; -#if !defined SLSI_TEST_DEV && defined CONFIG_ANDROID - struct wake_lock wlan_wl_roam; -#endif - struct slsi_sig_send sig_wait; - struct slsi_skb_work rx_dbg_sap; - atomic_t tx_host_tag[SLSI_LLS_AC_MAX]; -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - struct slsi_mutex device_config_mutex; -#else - /* a std mutex */ - struct mutex device_config_mutex; -#endif - struct slsi_dev_config device_config; - - struct notifier_block inetaddr_notifier; -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - struct notifier_block inet6addr_notifier; -#endif - - struct workqueue_struct *device_wq; /* Driver Workqueue */ - enum slsi_p2p_states p2p_state; /* Store current P2P operation */ - - enum slsi_wlan_state wlan_unsync_vif_state; /* Store current sate of unsync wlan vif */ - - int current_tspec_id; - int tspec_error_code; - u8 p2p_group_exp_frame; /* Next expected Public action frame subtype from peer */ - bool initial_scan; - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - struct slsi_gscan *gscan; - struct slsi_gscan_result *gscan_hash_table[SLSI_GSCAN_HASH_TABLE_SIZE]; - int num_gscan_results; - int buffer_threshold; - int buffer_consumed; - struct slsi_bucket bucket[SLSI_GSCAN_MAX_BUCKETS]; - struct list_head hotlist_results; - bool epno_active; -#endif -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - u8 scan_mac_addr[6]; - bool scan_addr_set; -#endif -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - int minor_prof; -#endif - struct slsi_ba_session_rx rx_ba_buffer_pool[SLSI_MAX_RX_BA_SESSIONS]; - struct slsi_spinlock rx_ba_buffer_pool_lock; - bool fail_reported; - bool p2p_certif; /* Set to true to idenitfy p2p_certification testing is going on*/ - bool mlme_blocked; /* When true do not send mlme signals to FW */ - atomic_t debug_inds; - int recovery_next_state; - struct completion recovery_remove_completion; - struct completion recovery_stop_completion; - struct completion recovery_completed; - int recovery_status; - struct slsi_ssid_map ssid_map[SLSI_SCAN_SSID_MAP_MAX]; - bool band_5g_supported; - int supported_2g_channels[14]; - int supported_5g_channels[25]; - int enabled_channel_count; - bool fw_ht_enabled; - u8 fw_ht_cap[4]; /* HT capabilities is 21 bytes but host is never intersted in last 17 bytes*/ - bool fw_vht_enabled; - u8 fw_vht_cap[4]; -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - u8 wifi_sharing_5ghz_channel[8]; - int valid_5g_freq[25]; - int wifi_sharing_5g_restricted_channels[25]; - int num_5g_restricted_channels; -#endif - bool fw_SoftAp_2g_40mhz_enabled; - bool nan_enabled; - u16 assoc_result_code; /* Status of latest association in STA mode */ - bool allow_switch_40_mhz; /* Used in AP cert to disable HT40 when not configured */ - bool allow_switch_80_mhz; /* Used in AP cert to disable VHT when not configured */ -#ifdef CONFIG_SCSC_WLAN_AP_INFO_FILE - /* Parameters in '/data/vendor/conn/.softap.info' */ - bool dualband_concurrency; - u32 softap_max_client; -#endif - u32 fw_dwell_time; - int lls_num_radio; - -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - struct slsi_mutex logger_mutex; -#else - /* a std mutex */ - struct mutex logger_mutex; -#endif - struct slsi_traffic_mon_clients traffic_mon_clients; - /*Store vif index corresponding to rtt id for FTM*/ - u16 rtt_vif[8]; - bool acs_channel_switched; - int recovery_timeout; /* ms autorecovery completion timeout */ -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - bool fw_mac_randomization_enabled; -#endif - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - bool enhanced_pkt_filter_enabled; -#endif -#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER - bool abnormal_multicast_pkt_filter_enabled; -#endif -}; - -/* Compact representation of channels a ESS has been seen on - * This is sized correctly for the Channels we currently support, - * 2.4Ghz Channels 1 - 14 - * 5 Ghz Channels Uni1, Uni2 and Uni3 - */ -struct slsi_roaming_network_map_entry { - struct list_head list; - unsigned long last_seen_jiffies; /* Timestamp of the last time we saw this ESS */ - struct cfg80211_ssid ssid; /* SSID of the ESS */ - u8 initial_bssid[ETH_ALEN]; /* Bssid of the first ap seen in this ESS */ - bool only_one_ap_seen; /* Has more than one AP for this ESS been seen */ - u16 channels_24_ghz; /* 2.4 Ghz Channels Bit Map */ - /* 5 Ghz Channels Bit Map - * channels_5_ghz & 0x000000FF = 4 Uni1 Channels - * channels_5_ghz & 0x00FFFF00 = 15 Uni2 Channels - * channels_5_ghz & 0xFF000000 = 5 Uni3 Channels - */ - u32 channels_5_ghz; -}; - -#define LLC_SNAP_HDR_LEN 8 -struct llc_snap_hdr { - u8 llc_dsap; - u8 llc_ssap; - u8 llc_ctrl; - u8 snap_oui[3]; - u16 snap_type; -} __packed; - -void slsi_rx_data_deliver_skb(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, bool from_ba_timer); -void slsi_rx_dbg_sap_work(struct work_struct *work); -void slsi_rx_netdev_data_work(struct work_struct *work); -void slsi_rx_netdev_mlme_work(struct work_struct *work); -int slsi_rx_enqueue_netdev_mlme(struct slsi_dev *sdev, struct sk_buff *skb, u16 vif); -void slsi_rx_scan_pass_to_cfg80211(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_buffered_frames(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer); -int slsi_rx_blocking_signals(struct slsi_dev *sdev, struct sk_buff *skb); -void slsi_scan_complete(struct slsi_dev *sdev, struct net_device *dev, u16 scan_id, bool aborted); - -void slsi_tx_pause_queues(struct slsi_dev *sdev); -void slsi_tx_unpause_queues(struct slsi_dev *sdev); -int slsi_tx_control(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -int slsi_tx_data_lower(struct slsi_dev *sdev, struct sk_buff *skb); -bool slsi_is_test_mode_enabled(void); -bool slsi_is_rf_test_mode_enabled(void); -int slsi_check_rf_test_mode(void); -void slsi_regd_deinit(struct slsi_dev *sdev); -void slsi_init_netdev_mac_addr(struct slsi_dev *sdev); -bool slsi_dev_lls_supported(void); -bool slsi_dev_gscan_supported(void); -bool slsi_dev_epno_supported(void); -bool slsi_dev_vo_vi_block_ack(void); -int slsi_dev_get_scan_result_count(void); -bool slsi_dev_llslogs_supported(void); -int slsi_dev_nan_supported(struct slsi_dev *sdev); -void slsi_regd_init(struct slsi_dev *sdev); -bool slsi_dev_rtt_supported(void); - -static inline u16 slsi_tx_host_tag(struct slsi_dev *sdev, enum slsi_traffic_q tq) -{ - /* host_tag: - * bit 0,1 = trafficqueue identifier - * bit 2-15 = incremental number - * So increment by 4 to get bit 2-15 a incremental sequence - */ - return (u16)atomic_add_return(4, &sdev->tx_host_tag[tq]); -} - -static inline u16 slsi_tx_mgmt_host_tag(struct slsi_dev *sdev) -{ - /* Doesn't matter which traffic queue host tag is selected.*/ - return slsi_tx_host_tag(sdev, 0); -} - -static inline struct net_device *slsi_get_netdev_rcu(struct slsi_dev *sdev, u16 ifnum) -{ - WARN_ON(!rcu_read_lock_held()); - if (ifnum > CONFIG_SCSC_WLAN_MAX_INTERFACES) { - /* WARN(1, "ifnum:%d", ifnum); WARN() is used like this to avoid Coverity Error */ - return NULL; - } - return rcu_dereference(sdev->netdev[ifnum]); -} - -static inline struct net_device *slsi_get_netdev_locked(struct slsi_dev *sdev, u16 ifnum) -{ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->netdev_add_remove_mutex)); - if (ifnum > CONFIG_SCSC_WLAN_MAX_INTERFACES) { - WARN(1, "ifnum:%d", ifnum); /* WARN() is used like this to avoid Coverity Error */ - return NULL; - } - return sdev->netdev[ifnum]; -} - -static inline struct net_device *slsi_get_netdev(struct slsi_dev *sdev, u16 ifnum) -{ - struct net_device *dev; - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - dev = slsi_get_netdev_locked(sdev, ifnum); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - return dev; -} - -static inline int slsi_get_supported_mode(const u8 *peer_ie) -{ - const u8 *peer_ie_data; - u8 peer_ie_len; - int i; - int supported_rate; - - peer_ie_len = peer_ie[1]; - peer_ie_data = &peer_ie[2]; - for (i = 0; i < peer_ie_len; i++) { - supported_rate = ((peer_ie_data[i] & 0x7F) / 2); - if (supported_rate > 11) - return SLSI_80211_MODE_11G; - } - return SLSI_80211_MODE_11B; -} - -/* Names of full mode HCF files */ -extern char *slsi_mib_file; -extern char *slsi_mib_file2; - -#endif diff --git a/drivers/net/wireless/scsc/fapi.h b/drivers/net/wireless/scsc/fapi.h deleted file mode 100644 index 2148bebe6fb9..000000000000 --- a/drivers/net/wireless/scsc/fapi.h +++ /dev/null @@ -1,4671 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef _FAPI_H__ -#define _FAPI_H__ - -#include -#include -#include "utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef CONFIG_SCSC_SMAPPER -struct slsi_skb_cb { - u32 sig_length; - u32 data_length; - u32 frame_format; - u32 colour; -}; - -static inline struct slsi_skb_cb *slsi_skb_cb_get(struct sk_buff *skb) -{ - return (struct slsi_skb_cb *)skb->cb; -} - -static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb) -{ - BUILD_BUG_ON(sizeof(struct slsi_skb_cb) > sizeof(skb->cb)); - - memset(skb->cb, 0, sizeof(struct slsi_skb_cb)); - return slsi_skb_cb_get(skb); -} -#endif - -#define FAPI_SIG_TYPE_MASK 0x0F00 -#define FAPI_SIG_TYPE_REQ 0x0000 -#define FAPI_SIG_TYPE_CFM 0x0100 -#define FAPI_SIG_TYPE_RES 0x0200 -#define FAPI_SIG_TYPE_IND 0x0300 - -#define FAPI_SAP_TYPE_MASK 0xF000 -#define FAPI_SAP_TYPE_MA 0x1000 -#define FAPI_SAP_TYPE_MLME 0x2000 -#define FAPI_SAP_TYPE_DEBUG 0x8000 -#define FAPI_SAP_TYPE_TEST 0x9000 - -#define FAPI_DEBUG_SAP_ENG_VERSION 0x0001 -#define FAPI_DATA_SAP_ENG_VERSION 0x0001 -#define FAPI_CONTROL_SAP_ENG_VERSION 0x0009 -#define FAPI_TEST_SAP_ENG_VERSION 0x0010 -#define FAPI_DEBUG_SAP_VERSION 0x0d03 -#define FAPI_TEST_SAP_VERSION 0x0e00 -#define FAPI_DATA_SAP_VERSION 0x0e00 -#define FAPI_CONTROL_SAP_VERSION 0x0e02 - -#define FAPI_ACLPOLICY_BLACKLIST 0x0000 -#define FAPI_ACLPOLICY_WHITELIST 0x0001 - -#define FAPI_ACTION_STOP 0x0000 -#define FAPI_ACTION_START 0x0001 - -#define FAPI_APFFILTERMODE_DISABLED 0x0000 -#define FAPI_APFFILTERMODE_SUSPEND 0x0001 -#define FAPI_APFFILTERMODE_ACTIVE 0x0002 - -#define FAPI_AUTHENTICATIONTYPE_OPEN_SYSTEM 0x0000 -#define FAPI_AUTHENTICATIONTYPE_SHARED_KEY 0x0001 -#define FAPI_AUTHENTICATIONTYPE_SAE 0x0003 -#define FAPI_AUTHENTICATIONTYPE_LEAP 0x0080 - -#define FAPI_BANDWIDTH_20_MHZ 0x0 -#define FAPI_BANDWIDTH_40_MHZ 0x1 -#define FAPI_BANDWIDTH_80_MHZ 0x2 -#define FAPI_BANDWIDTH_160_MHZ 0x3 - -#define FAPI_BLOCKACKPOLICY_DELAYED_BLOCKACK 0x0 -#define FAPI_BLOCKACKPOLICY_IMMEDIATE_BLOCKACK 0x1 - -#define FAPI_BULKDATADESCRIPTOR_INLINE 0x0000 -#define FAPI_BULKDATADESCRIPTOR_SMAPPER 0x0001 - -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ 0x00 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ 0x01 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ 0x02 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ 0x03 - -#define FAPI_CONNECTIONTYPE_WLAN_INFRASTRUCTURE 0x0000 -#define FAPI_CONNECTIONTYPE_P2P_OPERATION 0x0001 -#define FAPI_CONNECTIONTYPE_NAN_FURTHER_SERVICE_SLOT 0x0004 -#define FAPI_CONNECTIONTYPE_WLAN_RANGING 0x0005 - -#define FAPI_CWSTARTFLAGS_NONE 0x0000 -#define FAPI_CWSTARTFLAGS_SCAN_CHANNEL 0x0001 - -#define FAPI_CWTYPE_SINE 0x0000 -#define FAPI_CWTYPE_RAMP 0x0001 -#define FAPI_CWTYPE_TWO_TONE 0x0002 -#define FAPI_CWTYPE_DC 0x0003 -#define FAPI_CWTYPE_PRN 0x0004 - -#define FAPI_DATARATE_11B20_1MBPS 0x0001 -#define FAPI_DATARATE_11B20_2MBPS 0x0002 -#define FAPI_DATARATE_11B20_5M5BPS 0x0005 -#define FAPI_DATARATE_11B20_11MBPS 0x000b -#define FAPI_DATARATE_11A20_6MBPS 0x2006 -#define FAPI_DATARATE_11A20_9MBPS 0x2009 -#define FAPI_DATARATE_11A20_12MBPS 0x200c -#define FAPI_DATARATE_11A20_18MBPS 0x2012 -#define FAPI_DATARATE_11A20_24MBPS 0x2018 -#define FAPI_DATARATE_11A20_36MBPS 0x2024 -#define FAPI_DATARATE_11A20_48MBPS 0x2030 -#define FAPI_DATARATE_11A20_54MBPS 0x2036 -#define FAPI_DATARATE_11N20_6M5BPS 0x4000 -#define FAPI_DATARATE_11N20_13MBPS 0x4001 -#define FAPI_DATARATE_11N20_19M5BPS 0x4002 -#define FAPI_DATARATE_11N20_26MBPS 0x4003 -#define FAPI_DATARATE_11N20_39MBPS 0x4004 -#define FAPI_DATARATE_11N20_52MBPS 0x4005 -#define FAPI_DATARATE_11N20_58M5BPS 0x4006 -#define FAPI_DATARATE_11N20_65MBPS 0x4007 -#define FAPI_DATARATE_11N20_7M2BPS_SGI 0x4040 -#define FAPI_DATARATE_11N20_14M4BPS_SGI 0x4041 -#define FAPI_DATARATE_11N20_21M7BPS_SGI 0x4042 -#define FAPI_DATARATE_11N20_28M9BPS_SGI 0x4043 -#define FAPI_DATARATE_11N20_43M3BPS_SGI 0x4044 -#define FAPI_DATARATE_11N20_57M8BPS_SGI 0x4045 -#define FAPI_DATARATE_11N20_65MBPS_SGI 0x4046 -#define FAPI_DATARATE_11N20_72M2BPS_SGI 0x4047 -#define FAPI_DATARATE_11N20_13MBPS_NSS2 0x4088 -#define FAPI_DATARATE_11N20_26MBPS_NSS2 0x4089 -#define FAPI_DATARATE_11N20_39MBPS_NSS2 0x408a -#define FAPI_DATARATE_11N20_52MBPS_NSS2 0x408b -#define FAPI_DATARATE_11N20_78MBPS_NSS2 0x408c -#define FAPI_DATARATE_11N20_104MBPS_NSS2 0x408d -#define FAPI_DATARATE_11N20_117MBPS_NSS2 0x408e -#define FAPI_DATARATE_11N20_130MBPS_NSS2 0x408f -#define FAPI_DATARATE_11N20_14M4BPS_SGI_NSS2 0x40c8 -#define FAPI_DATARATE_11N20_28M9BPS_SGI_NSS2 0x40c9 -#define FAPI_DATARATE_11N20_43M3BPS_SGI_NSS2 0x40ca -#define FAPI_DATARATE_11N20_57M8BPS_SGI_NSS2 0x40cb -#define FAPI_DATARATE_11N20_86M7BPS_SGI_NSS2 0x40cc -#define FAPI_DATARATE_11N20_115M6BPS_SGI_NSS2 0x40cd -#define FAPI_DATARATE_11N20_130MBPS_SGI_NSS2 0x40ce -#define FAPI_DATARATE_11N20_144M4BPS_SGI_NSS2 0x40cf -#define FAPI_DATARATE_11N40_13M5BPS 0x4400 -#define FAPI_DATARATE_11N40_27MBPS 0x4401 -#define FAPI_DATARATE_11N40_40M5BPS 0x4402 -#define FAPI_DATARATE_11N40_54MBPS 0x4403 -#define FAPI_DATARATE_11N40_81MBPS 0x4404 -#define FAPI_DATARATE_11N40_108MBPS 0x4405 -#define FAPI_DATARATE_11N40_121M5BPS 0x4406 -#define FAPI_DATARATE_11N40_135MBPS 0x4407 -#define FAPI_DATARATE_11N40_6MBPS 0x4420 -#define FAPI_DATARATE_11N40_15MBPS_SGI 0x4440 -#define FAPI_DATARATE_11N40_30MBPS_SGI 0x4441 -#define FAPI_DATARATE_11N40_45MBPS_SGI 0x4442 -#define FAPI_DATARATE_11N40_60MBPS_SGI 0x4443 -#define FAPI_DATARATE_11N40_90MBPS_SGI 0x4444 -#define FAPI_DATARATE_11N40_120MBPS_SGI 0x4445 -#define FAPI_DATARATE_11N40_135MBPS_SGI 0x4446 -#define FAPI_DATARATE_11N40_150MBPS_SGI 0x4447 -#define FAPI_DATARATE_11N40_6M7BPS_SGI 0x4460 -#define FAPI_DATARATE_11N40_27MBPS_NSS2 0x4488 -#define FAPI_DATARATE_11N40_54MBPS_NSS2 0x4489 -#define FAPI_DATARATE_11N40_81MBPS_NSS2 0x448a -#define FAPI_DATARATE_11N40_108MBPS_NSS2 0x448b -#define FAPI_DATARATE_11N40_162MBPS_NSS2 0x448c -#define FAPI_DATARATE_11N40_216MBPS_NSS2 0x448d -#define FAPI_DATARATE_11N40_243MBPS_NSS2 0x448e -#define FAPI_DATARATE_11N40_270MBPS_NSS2 0x448f -#define FAPI_DATARATE_11N40_30MBPS_SGI_NSS2 0x44c8 -#define FAPI_DATARATE_11N40_60MBPS_SGI_NSS2 0x44c9 -#define FAPI_DATARATE_11N40_90MBPS_SGI_NSS2 0x44ca -#define FAPI_DATARATE_11N40_120MBPS_SGI_NSS2 0x44cb -#define FAPI_DATARATE_11N40_180MBPS_SGI_NSS2 0x44cc -#define FAPI_DATARATE_11N40_240MBPS_SGI_NSS2 0x44cd -#define FAPI_DATARATE_11N40_270MBPS_SGI_NSS2 0x44ce -#define FAPI_DATARATE_11N40_300MBPS_SGI_NSS2 0x44cf -#define FAPI_DATARATE_11AC20_6M5BPS 0x6000 -#define FAPI_DATARATE_11AC20_13MBPS 0x6001 -#define FAPI_DATARATE_11AC20_19M5BPS 0x6002 -#define FAPI_DATARATE_11AC20_26MBPS 0x6003 -#define FAPI_DATARATE_11AC20_39MBPS 0x6004 -#define FAPI_DATARATE_11AC20_52MBPS 0x6005 -#define FAPI_DATARATE_11AC20_58M5BPS 0x6006 -#define FAPI_DATARATE_11AC20_65MBPS 0x6007 -#define FAPI_DATARATE_11AC20_78MBPS 0x6008 -#define FAPI_DATARATE_11AC20_97M5BPS 0x600a -#define FAPI_DATARATE_11AC20_7M2BPS_SGI 0x6040 -#define FAPI_DATARATE_11AC20_14M4BPS_SGI 0x6041 -#define FAPI_DATARATE_11AC20_21M7BPS_SGI 0x6042 -#define FAPI_DATARATE_11AC20_28M9BPS_SGI 0x6043 -#define FAPI_DATARATE_11AC20_43M3BPS_SGI 0x6044 -#define FAPI_DATARATE_11AC20_57M8BPS_SGI 0x6045 -#define FAPI_DATARATE_11AC20_65MBPS_SGI 0x6046 -#define FAPI_DATARATE_11AC20_72M2BPS_SGI 0x6047 -#define FAPI_DATARATE_11AC20_86M7BPS_SGI 0x6048 -#define FAPI_DATARATE_11AC20_108M3BPS_SGI 0x604a -#define FAPI_DATARATE_11AC20_13MBPS_NSS2 0x6080 -#define FAPI_DATARATE_11AC20_26MBPS_NSS2 0x6081 -#define FAPI_DATARATE_11AC20_39MBPS_NSS2 0x6082 -#define FAPI_DATARATE_11AC20_52MBPS_NSS2 0x6083 -#define FAPI_DATARATE_11AC20_78MBPS_NSS2 0x6084 -#define FAPI_DATARATE_11AC20_104MBPS_NSS2 0x6085 -#define FAPI_DATARATE_11AC20_117MBPS_NSS2 0x6086 -#define FAPI_DATARATE_11AC20_130MBPS_NSS2 0x6087 -#define FAPI_DATARATE_11AC20_156MBPS_NSS2 0x6088 -#define FAPI_DATARATE_11AC20_195MBPS_NSS2 0x608a -#define FAPI_DATARATE_11AC20_14M4BPS_SGI_NSS2 0x60c0 -#define FAPI_DATARATE_11AC20_28M9BPS_SGI_NSS2 0x60c1 -#define FAPI_DATARATE_11AC20_43M3BPS_SGI_NSS2 0x60c2 -#define FAPI_DATARATE_11AC20_57M8BPS_SGI_NSS2 0x60c3 -#define FAPI_DATARATE_11AC20_86M7BPS_SGI_NSS2 0x60c4 -#define FAPI_DATARATE_11AC20_115M6BPS_SGI_NSS2 0x60c5 -#define FAPI_DATARATE_11AC20_130MBPS_SGI_NSS2 0x60c6 -#define FAPI_DATARATE_11AC20_144M4BPS_SGI_NSS2 0x60c7 -#define FAPI_DATARATE_11AC20_173M3BPS_SGI_NSS2 0x60c8 -#define FAPI_DATARATE_11AC20_216M7BPS_SGI_NSS2 0x60ca -#define FAPI_DATARATE_11AC40_13M5BPS 0x6400 -#define FAPI_DATARATE_11AC40_27MBPS 0x6401 -#define FAPI_DATARATE_11AC40_40M5BPS 0x6402 -#define FAPI_DATARATE_11AC40_54MBPS 0x6403 -#define FAPI_DATARATE_11AC40_81MBPS 0x6404 -#define FAPI_DATARATE_11AC40_108MBPS 0x6405 -#define FAPI_DATARATE_11AC40_121M5BPS 0x6406 -#define FAPI_DATARATE_11AC40_135MBPS 0x6407 -#define FAPI_DATARATE_11AC40_162MBPS 0x6408 -#define FAPI_DATARATE_11AC40_180MBPS 0x6409 -#define FAPI_DATARATE_11AC40_202M5BPS 0x640a -#define FAPI_DATARATE_11AC40_225MBPS 0x640b -#define FAPI_DATARATE_11AC40_15MBPS_SGI 0x6440 -#define FAPI_DATARATE_11AC40_30MBPS_SGI 0x6441 -#define FAPI_DATARATE_11AC40_45MBPS_SGI 0x6442 -#define FAPI_DATARATE_11AC40_60MBPS_SGI 0x6443 -#define FAPI_DATARATE_11AC40_90MBPS_SGI 0x6444 -#define FAPI_DATARATE_11AC40_120MBPS_SGI 0x6445 -#define FAPI_DATARATE_11AC40_135MBPS_SGI 0x6446 -#define FAPI_DATARATE_11AC40_150MBPS_SGI 0x6447 -#define FAPI_DATARATE_11AC40_180MBPS_SGI 0x6448 -#define FAPI_DATARATE_11AC40_200MBPS_SGI 0x6449 -#define FAPI_DATARATE_11AC40_225MBPS_SGI 0x644a -#define FAPI_DATARATE_11AC40_250MBPS_SGI 0x644b -#define FAPI_DATARATE_11AC40_27MBPS_NSS2 0x6480 -#define FAPI_DATARATE_11AC40_54MBPS_NSS2 0x6481 -#define FAPI_DATARATE_11AC40_81MBPS_NSS2 0x6482 -#define FAPI_DATARATE_11AC40_108MBPS_NSS2 0x6483 -#define FAPI_DATARATE_11AC40_162MBPS_NSS2 0x6484 -#define FAPI_DATARATE_11AC40_216MBPS_NSS2 0x6485 -#define FAPI_DATARATE_11AC40_243MBPS_NSS2 0x6486 -#define FAPI_DATARATE_11AC40_270MBPS_NSS2 0x6487 -#define FAPI_DATARATE_11AC40_324MBPS_NSS2 0x6488 -#define FAPI_DATARATE_11AC40_360MBPS_NSS2 0x6489 -#define FAPI_DATARATE_11AC40_405MBPS_NSS2 0x648a -#define FAPI_DATARATE_11AC40_450MBPS_NSS2 0x648b -#define FAPI_DATARATE_11AC40_30MBPS_SGI_NSS2 0x64c0 -#define FAPI_DATARATE_11AC40_60MBPS_SGI_NSS2 0x64c1 -#define FAPI_DATARATE_11AC40_90MBPS_SGI_NSS2 0x64c2 -#define FAPI_DATARATE_11AC40_120MBPS_SGI_NSS2 0x64c3 -#define FAPI_DATARATE_11AC40_180MBPS_SGI_NSS2 0x64c4 -#define FAPI_DATARATE_11AC40_240MBPS_SGI_NSS2 0x64c5 -#define FAPI_DATARATE_11AC40_270MBPS_SGI_NSS2 0x64c6 -#define FAPI_DATARATE_11AC40_300MBPS_SGI_NSS2 0x64c7 -#define FAPI_DATARATE_11AC40_360MBPS_SGI_NSS2 0x64c8 -#define FAPI_DATARATE_11AC40_400MBPS_SGI_NSS2 0x64c9 -#define FAPI_DATARATE_11AC40_450MBPS_SGI_NSS2 0x64ca -#define FAPI_DATARATE_11AC40_500MBPS_SGI_NSS2 0x64cb -#define FAPI_DATARATE_11AC80_29M3BPS 0x6800 -#define FAPI_DATARATE_11AC80_58M5BPS 0x6801 -#define FAPI_DATARATE_11AC80_87M8BPS 0x6802 -#define FAPI_DATARATE_11AC80_117MBPS 0x6803 -#define FAPI_DATARATE_11AC80_175M5BPS 0x6804 -#define FAPI_DATARATE_11AC80_234MBPS 0x6805 -#define FAPI_DATARATE_11AC80_263M3BPS 0x6806 -#define FAPI_DATARATE_11AC80_292M5BPS 0x6807 -#define FAPI_DATARATE_11AC80_351MBPS 0x6808 -#define FAPI_DATARATE_11AC80_390MBPS 0x6809 -#define FAPI_DATARATE_11AC80_438M8BPS 0x680a -#define FAPI_DATARATE_11AC80_487M5BPS 0x680b -#define FAPI_DATARATE_11AC80_32M5BPS_SGI 0x6840 -#define FAPI_DATARATE_11AC80_65MBPS_SGI 0x6841 -#define FAPI_DATARATE_11AC80_97M5BPS_SGI 0x6842 -#define FAPI_DATARATE_11AC80_130MBPS_SGI 0x6843 -#define FAPI_DATARATE_11AC80_195MBPS_SGI 0x6844 -#define FAPI_DATARATE_11AC80_260MBPS_SGI 0x6845 -#define FAPI_DATARATE_11AC80_292M5BPS_SGI 0x6846 -#define FAPI_DATARATE_11AC80_325MBPS_SGI 0x6847 -#define FAPI_DATARATE_11AC80_390MBPS_SGI 0x6848 -#define FAPI_DATARATE_11AC80_433M3BPS_SGI 0x6849 -#define FAPI_DATARATE_11AC80_487M5BPS_SGI 0x684a -#define FAPI_DATARATE_11AC80_541M7BPS_SGI 0x684b -#define FAPI_DATARATE_11AC80_58M5BPS_NSS2 0x6880 -#define FAPI_DATARATE_11AC80_117MBPS_NSS2 0x6881 -#define FAPI_DATARATE_11AC80_175M5BPS_NSS2 0x6882 -#define FAPI_DATARATE_11AC80_234MBPS_NSS2 0x6883 -#define FAPI_DATARATE_11AC80_351MBPS_NSS2 0x6884 -#define FAPI_DATARATE_11AC80_468MBPS_NSS2 0x6885 -#define FAPI_DATARATE_11AC80_526M5BPS_NSS2 0x6886 -#define FAPI_DATARATE_11AC80_585MBPS_NSS2 0x6887 -#define FAPI_DATARATE_11AC80_702MBPS_NSS2 0x6888 -#define FAPI_DATARATE_11AC80_780MBPS_NSS2 0x6889 -#define FAPI_DATARATE_11AC80_877M5BPS_NSS2 0x688a -#define FAPI_DATARATE_11AC80_975MBPS_NSS2 0x688b -#define FAPI_DATARATE_11AC80_65MBPS_SGI_NSS2 0x68c0 -#define FAPI_DATARATE_11AC80_130MBPS_SGI_NSS2 0x68c1 -#define FAPI_DATARATE_11AC80_195MBPS_SGI_NSS2 0x68c2 -#define FAPI_DATARATE_11AC80_260MBPS_SGI_NSS2 0x68c3 -#define FAPI_DATARATE_11AC80_390MBPS_SGI_NSS2 0x68c4 -#define FAPI_DATARATE_11AC80_520MBPS_SGI_NSS2 0x68c5 -#define FAPI_DATARATE_11AC80_585MBPS_SGI_NSS2 0x68c6 -#define FAPI_DATARATE_11AC80_650MBPS_SGI_NSS2 0x68c7 -#define FAPI_DATARATE_11AC80_780MBPS_SGI_NSS2 0x68c8 -#define FAPI_DATARATE_11AC80_866M7BPS_SGI_NSS2 0x68c9 -#define FAPI_DATARATE_11AC80_975MBPS_SGI_NSS2 0x68ca -#define FAPI_DATARATE_11AC80_1083M3BPS_SGI_NSS2 0x68cb -#define FAPI_DATARATE_11AC160_58M5BPS 0x6c00 -#define FAPI_DATARATE_11AC160_117MBPS 0x6c01 -#define FAPI_DATARATE_11AC160_175M5BPS 0x6c02 -#define FAPI_DATARATE_11AC160_234MBPS 0x6c03 -#define FAPI_DATARATE_11AC160_351MBPS 0x6c04 -#define FAPI_DATARATE_11AC160_468MBPS 0x6c05 -#define FAPI_DATARATE_11AC160_526M5BPS 0x6c06 -#define FAPI_DATARATE_11AC160_585MBPS 0x6c07 -#define FAPI_DATARATE_11AC160_702MBPS 0x6c08 -#define FAPI_DATARATE_11AC160_780MBPS 0x6c09 -#define FAPI_DATARATE_11AC160_877M5BPS 0x6c0a -#define FAPI_DATARATE_11AC160_975MBPS 0x6c0b -#define FAPI_DATARATE_11AC160_65MBPS_SGI 0x6c40 -#define FAPI_DATARATE_11AC160_130MBPS_SGI 0x6c41 -#define FAPI_DATARATE_11AC160_195MBPS_SGI 0x6c42 -#define FAPI_DATARATE_11AC160_260MBPS_SGI 0x6c43 -#define FAPI_DATARATE_11AC160_390MBPS_SGI 0x6c44 -#define FAPI_DATARATE_11AC160_520MBPS_SGI 0x6c45 -#define FAPI_DATARATE_11AC160_585MBPS_SGI 0x6c46 -#define FAPI_DATARATE_11AC160_650MBPS_SGI 0x6c47 -#define FAPI_DATARATE_11AC160_780MBPS_SGI 0x6c48 -#define FAPI_DATARATE_11AC160_866M7BPS_SGI 0x6c49 -#define FAPI_DATARATE_11AC160_975MBPS_SGI 0x6c4a -#define FAPI_DATARATE_11AC160_1083M3BPS_SGI 0x6c4b -#define FAPI_DATARATE_11AC160_117MBPS_NSS2 0x6c80 -#define FAPI_DATARATE_11AC160_234MBPS_NSS2 0x6c81 -#define FAPI_DATARATE_11AC160_351MBPS_NSS2 0x6c82 -#define FAPI_DATARATE_11AC160_468MBPS_NSS2 0x6c83 -#define FAPI_DATARATE_11AC160_702MBPS_NSS2 0x6c84 -#define FAPI_DATARATE_11AC160_936MBPS_NSS2 0x6c85 -#define FAPI_DATARATE_11AC160_1053MBPS_NSS2 0x6c86 -#define FAPI_DATARATE_11AC160_1170MBPS_NSS2 0x6c87 -#define FAPI_DATARATE_11AC160_1404MBPS_NSS2 0x6c88 -#define FAPI_DATARATE_11AC160_1560MBPS_NSS2 0x6c89 -#define FAPI_DATARATE_11AC160_1755MBPS_NSS2 0x6c8a -#define FAPI_DATARATE_11AC160_1950MBPS_NSS2 0x6c8b -#define FAPI_DATARATE_11AC160_130MBPS_SGI_NSS2 0x6cc0 -#define FAPI_DATARATE_11AC160_260MBPS_SGI_NSS2 0x6cc1 -#define FAPI_DATARATE_11AC160_390MBPS_SGI_NSS2 0x6cc2 -#define FAPI_DATARATE_11AC160_520MBPS_SGI_NSS2 0x6cc3 -#define FAPI_DATARATE_11AC160_780MBPS_SGI_NSS2 0x6cc4 -#define FAPI_DATARATE_11AC160_1040MBPS_SGI_NSS2 0x6cc5 -#define FAPI_DATARATE_11AC160_1170MBPS_SGI_NSS2 0x6cc6 -#define FAPI_DATARATE_11AC160_1300MBPS_SGI_NSS2 0x6cc7 -#define FAPI_DATARATE_11AC160_1560MBPS_SGI_NSS2 0x6cc8 -#define FAPI_DATARATE_11AC160_1733M3BPS_SGI_NSS2 0x6cc9 -#define FAPI_DATARATE_11AC160_1950MBPS_SGI_NSS2 0x6cca -#define FAPI_DATARATE_11AC160_2166M7BPS_SGI_NSS2 0x6ccb -#define FAPI_DATARATE_11AX20_8M6BPS_1GI 0x8000 -#define FAPI_DATARATE_11AX20_17M2BPS_1GI 0x8001 -#define FAPI_DATARATE_11AX20_25M8BPS_1GI 0x8002 -#define FAPI_DATARATE_11AX20_34M4BPS_1GI 0x8003 -#define FAPI_DATARATE_11AX20_51M6BPS_1GI 0x8004 -#define FAPI_DATARATE_11AX20_68M8BPS_1GI 0x8005 -#define FAPI_DATARATE_11AX20_77M4BPS_1GI 0x8006 -#define FAPI_DATARATE_11AX20_86MBPS_1GI 0x8007 -#define FAPI_DATARATE_11AX20_103M2BPS_1GI 0x8008 -#define FAPI_DATARATE_11AX20_114M7BPS_1GI 0x8009 -#define FAPI_DATARATE_11AX20_129MBPS_1GI 0x800a -#define FAPI_DATARATE_11AX20_143M4BPS_1GI 0x800b -#define FAPI_DATARATE_11AX20_8M1BPS_2GI 0x8010 -#define FAPI_DATARATE_11AX20_16M3BPS_2GI 0x8011 -#define FAPI_DATARATE_11AX20_24M4BPS_2GI 0x8012 -#define FAPI_DATARATE_11AX20_32M5BPS_2GI 0x8013 -#define FAPI_DATARATE_11AX20_48M8BPS_2GI 0x8014 -#define FAPI_DATARATE_11AX20_65MBPS_2GI 0x8015 -#define FAPI_DATARATE_11AX20_73M1BPS_2GI 0x8016 -#define FAPI_DATARATE_11AX20_81M3BPS_2GI 0x8017 -#define FAPI_DATARATE_11AX20_97M5BPS_2GI 0x8018 -#define FAPI_DATARATE_11AX20_108M3BPS_2GI 0x8019 -#define FAPI_DATARATE_11AX20_121M9BPS_2GI 0x801a -#define FAPI_DATARATE_11AX20_135M4BPS_2GI 0x801b -#define FAPI_DATARATE_11AX20_7M3BPS_4GI 0x8020 -#define FAPI_DATARATE_11AX20_14M6BPS_4GI 0x8021 -#define FAPI_DATARATE_11AX20_21M9BPS_4GI 0x8022 -#define FAPI_DATARATE_11AX20_29M3BPS_4GI 0x8023 -#define FAPI_DATARATE_11AX20_43M9BPS_4GI 0x8024 -#define FAPI_DATARATE_11AX20_58M5BPS_4GI 0x8025 -#define FAPI_DATARATE_11AX20_65M8BPS_4GI 0x8026 -#define FAPI_DATARATE_11AX20_73M1BPS_4GI 0x8027 -#define FAPI_DATARATE_11AX20_87M8BPS_4GI 0x8028 -#define FAPI_DATARATE_11AX20_97M5BPS_4GI 0x8029 -#define FAPI_DATARATE_11AX20_109M7BPS_4GI 0x802a -#define FAPI_DATARATE_11AX20_121M9BPS_4GI 0x802b -#define FAPI_DATARATE_11AX20_4M3BPS_1GI_DCM 0x8040 -#define FAPI_DATARATE_11AX20_8M6BPS_1GI_DCM 0x8041 -#define FAPI_DATARATE_11AX20_17M2BPS_1GI_DCM 0x8043 -#define FAPI_DATARATE_11AX20_25M8BPS_1GI_DCM 0x8044 -#define FAPI_DATARATE_11AX20_4MBPS_2GI_DCM 0x8050 -#define FAPI_DATARATE_11AX20_8M1BPS_2GI_DCM 0x8051 -#define FAPI_DATARATE_11AX20_16M3BPS_2GI_DCM 0x8053 -#define FAPI_DATARATE_11AX20_24M4BPS_2GI_DCM 0x8054 -#define FAPI_DATARATE_11AX20_3M6BPS_4GI_DCM 0x8060 -#define FAPI_DATARATE_11AX20_7M3BPS_4GI_DCM 0x8061 -#define FAPI_DATARATE_11AX20_14M6BPS_4GI_DCM 0x8063 -#define FAPI_DATARATE_11AX20_21M9BPS_4GI_DCM 0x8064 -#define FAPI_DATARATE_11AX20_17M2BPS_1GI_NSS2 0x8080 -#define FAPI_DATARATE_11AX20_34M4BPS_1GI_NSS2 0x8081 -#define FAPI_DATARATE_11AX20_51M6BPS_1GI_NSS2 0x8082 -#define FAPI_DATARATE_11AX20_68M8BPS_1GI_NSS2 0x8083 -#define FAPI_DATARATE_11AX20_103M2BPS_1GI_NSS2 0x8084 -#define FAPI_DATARATE_11AX20_137M6BPS_1GI_NSS2 0x8085 -#define FAPI_DATARATE_11AX20_154M9BPS_1GI_NSS2 0x8086 -#define FAPI_DATARATE_11AX20_172M1BPS_1GI_NSS2 0x8087 -#define FAPI_DATARATE_11AX20_206M5BPS_1GI_NSS2 0x8088 -#define FAPI_DATARATE_11AX20_229M4BPS_1GI_NSS2 0x8089 -#define FAPI_DATARATE_11AX20_258M1BPS_1GI_NSS2 0x808a -#define FAPI_DATARATE_11AX20_286M8BPS_1GI_NSS2 0x808b -#define FAPI_DATARATE_11AX20_16M3BPS_2GI_NSS2 0x8090 -#define FAPI_DATARATE_11AX20_32M5BPS_2GI_NSS2 0x8091 -#define FAPI_DATARATE_11AX20_48M8BPS_2GI_NSS2 0x8092 -#define FAPI_DATARATE_11AX20_65MBPS_2GI_NSS2 0x8093 -#define FAPI_DATARATE_11AX20_97M5BPS_2GI_NSS2 0x8094 -#define FAPI_DATARATE_11AX20_130MBPS_2GI_NSS2 0x8095 -#define FAPI_DATARATE_11AX20_146M3BPS_2GI_NSS2 0x8096 -#define FAPI_DATARATE_11AX20_162M5BPS_2GI_NSS2 0x8097 -#define FAPI_DATARATE_11AX20_195MBPS_2GI_NSS2 0x8098 -#define FAPI_DATARATE_11AX20_216M7BPS_2GI_NSS2 0x8099 -#define FAPI_DATARATE_11AX20_243M8BPS_2GI_NSS2 0x809a -#define FAPI_DATARATE_11AX20_270M8BPS_2GI_NSS2 0x809b -#define FAPI_DATARATE_11AX20_14M6BPS_4GI_NSS2 0x80a0 -#define FAPI_DATARATE_11AX20_29M3BPS_4GI_NSS2 0x80a1 -#define FAPI_DATARATE_11AX20_43M9BPS_4GI_NSS2 0x80a2 -#define FAPI_DATARATE_11AX20_58M5BPS_4GI_NSS2 0x80a3 -#define FAPI_DATARATE_11AX20_87M8BPS_4GI_NSS2 0x80a4 -#define FAPI_DATARATE_11AX20_117MBPS_4GI_NSS2 0x80a5 -#define FAPI_DATARATE_11AX20_131M6BPS_4GI_NSS2 0x80a6 -#define FAPI_DATARATE_11AX20_146M3BPS_4GI_NSS2 0x80a7 -#define FAPI_DATARATE_11AX20_175M5BPS_4GI_NSS2 0x80a8 -#define FAPI_DATARATE_11AX20_195MBPS_4GI_NSS2 0x80a9 -#define FAPI_DATARATE_11AX20_219M4BPS_4GI_NSS2 0x80aa -#define FAPI_DATARATE_11AX20_243M8BPS_4GI_NSS2 0x80ab -#define FAPI_DATARATE_11AX20_8M6BPS_1GI_NSS2_DCM 0x80c0 -#define FAPI_DATARATE_11AX20_17M2BPS_1GI_NSS2_DCM 0x80c1 -#define FAPI_DATARATE_11AX20_34M4BPS_1GI_NSS2_DCM 0x80c3 -#define FAPI_DATARATE_11AX20_51M6BPS_1GI_NSS2_DCM 0x80c4 -#define FAPI_DATARATE_11AX20_8M1BPS_2GI_NSS2_DCM 0x80d0 -#define FAPI_DATARATE_11AX20_16M3BPS_2GI_NSS2_DCM 0x80d1 -#define FAPI_DATARATE_11AX20_32M5BPS_2GI_NSS2_DCM 0x80d3 -#define FAPI_DATARATE_11AX20_48M8BPS_2GI_NSS2_DCM 0x80d4 -#define FAPI_DATARATE_11AX20_7M3BPS_4GI_NSS2_DCM 0x80e0 -#define FAPI_DATARATE_11AX20_14M6BPS_4GI_NSS2_DCM 0x80e1 -#define FAPI_DATARATE_11AX20_29M3BPS_4GI_NSS2_DCM 0x80e3 -#define FAPI_DATARATE_11AX20_43M9BPS_4GI_NSS2_DCM 0x80e4 -#define FAPI_DATARATE_11AX40_17M2BPS_1GI 0x8400 -#define FAPI_DATARATE_11AX40_34M4BPS_1GI 0x8401 -#define FAPI_DATARATE_11AX40_51M6BPS_1GI 0x8402 -#define FAPI_DATARATE_11AX40_68M8BPS_1GI 0x8403 -#define FAPI_DATARATE_11AX40_103M2BPS_1GI 0x8404 -#define FAPI_DATARATE_11AX40_137M6BPS_1GI 0x8405 -#define FAPI_DATARATE_11AX40_154M9BPS_1GI 0x8406 -#define FAPI_DATARATE_11AX40_172M1BPS_1GI 0x8407 -#define FAPI_DATARATE_11AX40_206M5BPS_1GI 0x8408 -#define FAPI_DATARATE_11AX40_229M4BPS_1GI 0x8409 -#define FAPI_DATARATE_11AX40_258M1BPS_1GI 0x840a -#define FAPI_DATARATE_11AX40_286M8BPS_1GI 0x840b -#define FAPI_DATARATE_11AX40_16M3BPS_2GI 0x8410 -#define FAPI_DATARATE_11AX40_32M5BPS_2GI 0x8411 -#define FAPI_DATARATE_11AX40_48M8BPS_2GI 0x8412 -#define FAPI_DATARATE_11AX40_65MBPS_2GI 0x8413 -#define FAPI_DATARATE_11AX40_97M5BPS_2GI 0x8414 -#define FAPI_DATARATE_11AX40_130MBPS_2GI 0x8415 -#define FAPI_DATARATE_11AX40_146M3BPS_2GI 0x8416 -#define FAPI_DATARATE_11AX40_162M5BPS_2GI 0x8417 -#define FAPI_DATARATE_11AX40_195MBPS_2GI 0x8418 -#define FAPI_DATARATE_11AX40_216M7BPS_2GI 0x8419 -#define FAPI_DATARATE_11AX40_243M8BPS_2GI 0x841a -#define FAPI_DATARATE_11AX40_270M8BPS_2GI 0x841b -#define FAPI_DATARATE_11AX40_14M6BPS_4GI 0x8420 -#define FAPI_DATARATE_11AX40_29M3BPS_4GI 0x8421 -#define FAPI_DATARATE_11AX40_43M9BPS_4GI 0x8422 -#define FAPI_DATARATE_11AX40_58M5BPS_4GI 0x8423 -#define FAPI_DATARATE_11AX40_87M8BPS_4GI 0x8424 -#define FAPI_DATARATE_11AX40_117MBPS_4GI 0x8425 -#define FAPI_DATARATE_11AX40_131M6BPS_4GI 0x8426 -#define FAPI_DATARATE_11AX40_146M3BPS_4GI 0x8427 -#define FAPI_DATARATE_11AX40_175M5BPS_4GI 0x8428 -#define FAPI_DATARATE_11AX40_195MBPS_4GI 0x8429 -#define FAPI_DATARATE_11AX40_219M4BPS_4GI 0x842a -#define FAPI_DATARATE_11AX40_243M8BPS_4GI 0x842b -#define FAPI_DATARATE_11AX40_8M6BPS_1GI_DCM 0x8440 -#define FAPI_DATARATE_11AX40_17M2BPS_1GI_DCM 0x8441 -#define FAPI_DATARATE_11AX40_34M4BPS_1GI_DCM 0x8443 -#define FAPI_DATARATE_11AX40_51M6BPS_1GI_DCM 0x8444 -#define FAPI_DATARATE_11AX40_8M1BPS_2GI_DCM 0x8450 -#define FAPI_DATARATE_11AX40_16M3BPS_2GI_DCM 0x8451 -#define FAPI_DATARATE_11AX40_32M5BPS_2GI_DCM 0x8453 -#define FAPI_DATARATE_11AX40_48M8BPS_2GI_DCM 0x8454 -#define FAPI_DATARATE_11AX40_7M3BPS_4GI_DCM 0x8460 -#define FAPI_DATARATE_11AX40_14M6BPS_4GI_DCM 0x8461 -#define FAPI_DATARATE_11AX40_29M3BPS_4GI_DCM 0x8463 -#define FAPI_DATARATE_11AX40_43M9BPS_4GI_DCM 0x8464 -#define FAPI_DATARATE_11AX40_34M4BPS_1GI_NSS2 0x8480 -#define FAPI_DATARATE_11AX40_68M8BPS_1GI_NSS2 0x8481 -#define FAPI_DATARATE_11AX40_103M2BPS_1GI_NSS2 0x8482 -#define FAPI_DATARATE_11AX40_137M6BPS_1GI_NSS2 0x8483 -#define FAPI_DATARATE_11AX40_206M5BPS_1GI_NSS2 0x8484 -#define FAPI_DATARATE_11AX40_275M3BPS_1GI_NSS2 0x8485 -#define FAPI_DATARATE_11AX40_309M7BPS_1GI_NSS2 0x8486 -#define FAPI_DATARATE_11AX40_344M1BPS_1GI_NSS2 0x8487 -#define FAPI_DATARATE_11AX40_412M9BPS_1GI_NSS2 0x8488 -#define FAPI_DATARATE_11AX40_458M8BPS_1GI_NSS2 0x8489 -#define FAPI_DATARATE_11AX40_516M2BPS_1GI_NSS2 0x848a -#define FAPI_DATARATE_11AX40_573M5BPS_1GI_NSS2 0x848b -#define FAPI_DATARATE_11AX40_32M5BPS_2GI_NSS2 0x8490 -#define FAPI_DATARATE_11AX40_65MBPS_2GI_NSS2 0x8491 -#define FAPI_DATARATE_11AX40_97M5BPS_2GI_NSS2 0x8492 -#define FAPI_DATARATE_11AX40_130MBPS_2GI_NSS2 0x8493 -#define FAPI_DATARATE_11AX40_195MBPS_2GI_NSS2 0x8494 -#define FAPI_DATARATE_11AX40_260MBPS_2GI_NSS2 0x8495 -#define FAPI_DATARATE_11AX40_292M5BPS_2GI_NSS2 0x8496 -#define FAPI_DATARATE_11AX40_325MBPS_2GI_NSS2 0x8497 -#define FAPI_DATARATE_11AX40_390MBPS_2GI_NSS2 0x8498 -#define FAPI_DATARATE_11AX40_433M3BPS_2GI_NSS2 0x8499 -#define FAPI_DATARATE_11AX40_487M5BPS_2GI_NSS2 0x849a -#define FAPI_DATARATE_11AX40_541M7BPS_2GI_NSS2 0x849b -#define FAPI_DATARATE_11AX40_29M3BPS_4GI_NSS2 0x84a0 -#define FAPI_DATARATE_11AX40_58M5BPS_4GI_NSS2 0x84a1 -#define FAPI_DATARATE_11AX40_87M8BPS_4GI_NSS2 0x84a2 -#define FAPI_DATARATE_11AX40_117MBPS_4GI_NSS2 0x84a3 -#define FAPI_DATARATE_11AX40_175M5BPS_4GI_NSS2 0x84a4 -#define FAPI_DATARATE_11AX40_234MBPS_4GI_NSS2 0x84a5 -#define FAPI_DATARATE_11AX40_263M3BPS_4GI_NSS2 0x84a6 -#define FAPI_DATARATE_11AX40_292M5BPS_4GI_NSS2 0x84a7 -#define FAPI_DATARATE_11AX40_351MBPS_4GI_NSS2 0x84a8 -#define FAPI_DATARATE_11AX40_390MBPS_4GI_NSS2 0x84a9 -#define FAPI_DATARATE_11AX40_438M8BPS_4GI_NSS2 0x84aa -#define FAPI_DATARATE_11AX40_487M5BPS_4GI_NSS2 0x84ab -#define FAPI_DATARATE_11AX40_17M2BPS_1GI_NSS2_DCM 0x84c0 -#define FAPI_DATARATE_11AX40_34M4BPS_1GI_NSS2_DCM 0x84c1 -#define FAPI_DATARATE_11AX40_68M8BPS_1GI_NSS2_DCM 0x84c3 -#define FAPI_DATARATE_11AX40_103M2BPS_1GI_NSS2_DCM 0x84c4 -#define FAPI_DATARATE_11AX40_16M3BPS_2GI_NSS2_DCM 0x84d0 -#define FAPI_DATARATE_11AX40_32M5BPS_2GI_NSS2_DCM 0x84d1 -#define FAPI_DATARATE_11AX40_65MBPS_2GI_NSS2_DCM 0x84d3 -#define FAPI_DATARATE_11AX40_97M5BPS_2GI_NSS2_DCM 0x84d4 -#define FAPI_DATARATE_11AX40_14M6BPS_4GI_NSS2_DCM 0x84e0 -#define FAPI_DATARATE_11AX40_29M3BPS_4GI_NSS2_DCM 0x84e1 -#define FAPI_DATARATE_11AX40_58M5BPS_4GI_NSS2_DCM 0x84e3 -#define FAPI_DATARATE_11AX40_87M8BPS_4GI_NSS2_DCM 0x84e4 -#define FAPI_DATARATE_11AX80_36MBPS_1GI 0x8800 -#define FAPI_DATARATE_11AX80_72M1BPS_1GI 0x8801 -#define FAPI_DATARATE_11AX80_108M1BPS_1GI 0x8802 -#define FAPI_DATARATE_11AX80_144M1BPS_1GI 0x8803 -#define FAPI_DATARATE_11AX80_216M2BPS_1GI 0x8804 -#define FAPI_DATARATE_11AX80_288M2BPS_1GI 0x8805 -#define FAPI_DATARATE_11AX80_324M3BPS_1GI 0x8806 -#define FAPI_DATARATE_11AX80_360M3BPS_1GI 0x8807 -#define FAPI_DATARATE_11AX80_432M4BPS_1GI 0x8808 -#define FAPI_DATARATE_11AX80_480M4BPS_1GI 0x8809 -#define FAPI_DATARATE_11AX80_540M4BPS_1GI 0x880a -#define FAPI_DATARATE_11AX80_600M4BPS_1GI 0x880b -#define FAPI_DATARATE_11AX80_34MBPS_2GI 0x8810 -#define FAPI_DATARATE_11AX80_68M1BPS_2GI 0x8811 -#define FAPI_DATARATE_11AX80_102M1BPS_2GI 0x8812 -#define FAPI_DATARATE_11AX80_136M1BPS_2GI 0x8813 -#define FAPI_DATARATE_11AX80_204M2BPS_2GI 0x8814 -#define FAPI_DATARATE_11AX80_272M2BPS_2GI 0x8815 -#define FAPI_DATARATE_11AX80_306M3BPS_2GI 0x8816 -#define FAPI_DATARATE_11AX80_340M3BPS_2GI 0x8817 -#define FAPI_DATARATE_11AX80_408M3BPS_2GI 0x8818 -#define FAPI_DATARATE_11AX80_453M7BPS_2GI 0x8819 -#define FAPI_DATARATE_11AX80_510M4BPS_2GI 0x881a -#define FAPI_DATARATE_11AX80_567M1BPS_2GI 0x881b -#define FAPI_DATARATE_11AX80_30M6BPS_4GI 0x8820 -#define FAPI_DATARATE_11AX80_61M3BPS_4GI 0x8821 -#define FAPI_DATARATE_11AX80_91M9BPS_4GI 0x8822 -#define FAPI_DATARATE_11AX80_122M5BPS_4GI 0x8823 -#define FAPI_DATARATE_11AX80_183M8BPS_4GI 0x8824 -#define FAPI_DATARATE_11AX80_245MBPS_4GI 0x8825 -#define FAPI_DATARATE_11AX80_275M6BPS_4GI 0x8826 -#define FAPI_DATARATE_11AX80_306M3BPS_4GI 0x8827 -#define FAPI_DATARATE_11AX80_367M5BPS_4GI 0x8828 -#define FAPI_DATARATE_11AX80_408M3BPS_4GI 0x8829 -#define FAPI_DATARATE_11AX80_459M4BPS_4GI 0x882a -#define FAPI_DATARATE_11AX80_510M4BPS_4GI 0x882b -#define FAPI_DATARATE_11AX80_18MBPS_1GI_DCM 0x8840 -#define FAPI_DATARATE_11AX80_36MBPS_1GI_DCM 0x8841 -#define FAPI_DATARATE_11AX80_72M1BPS_1GI_DCM 0x8843 -#define FAPI_DATARATE_11AX80_108M1BPS_1GI_DCM 0x8844 -#define FAPI_DATARATE_11AX80_17MBPS_2GI_DCM 0x8850 -#define FAPI_DATARATE_11AX80_34MBPS_2GI_DCM 0x8851 -#define FAPI_DATARATE_11AX80_68M1BPS_2GI_DCM 0x8853 -#define FAPI_DATARATE_11AX80_102M1BPS_2GI_DCM 0x8854 -#define FAPI_DATARATE_11AX80_15M3BPS_4GI_DCM 0x8860 -#define FAPI_DATARATE_11AX80_30M6BPS_4GI_DCM 0x8861 -#define FAPI_DATARATE_11AX80_61M3BPS_4GI_DCM 0x8863 -#define FAPI_DATARATE_11AX80_91M9BPS_4GI_DCM 0x8864 -#define FAPI_DATARATE_11AX80_72M1BPS_1GI_NSS2 0x8880 -#define FAPI_DATARATE_11AX80_144M1BPS_1GI_NSS2 0x8881 -#define FAPI_DATARATE_11AX80_216M2BPS_1GI_NSS2 0x8882 -#define FAPI_DATARATE_11AX80_288M2BPS_1GI_NSS2 0x8883 -#define FAPI_DATARATE_11AX80_432M4BPS_1GI_NSS2 0x8884 -#define FAPI_DATARATE_11AX80_576M5BPS_1GI_NSS2 0x8885 -#define FAPI_DATARATE_11AX80_648M5BPS_1GI_NSS2 0x8886 -#define FAPI_DATARATE_11AX80_720M6BPS_1GI_NSS2 0x8887 -#define FAPI_DATARATE_11AX80_864M7BPS_1GI_NSS2 0x8888 -#define FAPI_DATARATE_11AX80_960M7BPS_1GI_NSS2 0x8889 -#define FAPI_DATARATE_11AX80_1080M9BPS_1GI_NSS2 0x888a -#define FAPI_DATARATE_11AX80_1201MBPS_1GI_NSS2 0x888b -#define FAPI_DATARATE_11AX80_68M1BPS_2GI_NSS2 0x8890 -#define FAPI_DATARATE_11AX80_136M1BPS_2GI_NSS2 0x8891 -#define FAPI_DATARATE_11AX80_204M2BPS_2GI_NSS2 0x8892 -#define FAPI_DATARATE_11AX80_272M2BPS_2GI_NSS2 0x8893 -#define FAPI_DATARATE_11AX80_408M3BPS_2GI_NSS2 0x8894 -#define FAPI_DATARATE_11AX80_544M4BPS_2GI_NSS2 0x8895 -#define FAPI_DATARATE_11AX80_612M5BPS_2GI_NSS2 0x8896 -#define FAPI_DATARATE_11AX80_680M6BPS_2GI_NSS2 0x8897 -#define FAPI_DATARATE_11AX80_816M7BPS_2GI_NSS2 0x8898 -#define FAPI_DATARATE_11AX80_907M4BPS_2GI_NSS2 0x8899 -#define FAPI_DATARATE_11AX80_1020M8BPS_2GI_NSS2 0x889a -#define FAPI_DATARATE_11AX80_1134M3BPS_2GI_NSS2 0x889b -#define FAPI_DATARATE_11AX80_61M3BPS_4GI_NSS2 0x88a0 -#define FAPI_DATARATE_11AX80_122M5BPS_4GI_NSS2 0x88a1 -#define FAPI_DATARATE_11AX80_183M8BPS_4GI_NSS2 0x88a2 -#define FAPI_DATARATE_11AX80_245MBPS_4GI_NSS2 0x88a3 -#define FAPI_DATARATE_11AX80_367M5BP_4GI_NSS2 0x88a4 -#define FAPI_DATARATE_11AX80_490MBPS_4GI_NSS2 0x88a5 -#define FAPI_DATARATE_11AX80_551M3BPS_4GI_NSS2 0x88a6 -#define FAPI_DATARATE_11AX80_612M5BPS_4GI_NSS2 0x88a7 -#define FAPI_DATARATE_11AX80_735MBPS_4GI_NSS2 0x88a8 -#define FAPI_DATARATE_11AX80_816M6BPS_4GI_NSS2 0x88a9 -#define FAPI_DATARATE_11AX80_918M8BPS_4GI_NSS2 0x88aa -#define FAPI_DATARATE_11AX80_1020M8BPS_4GI_NSS2 0x88ab -#define FAPI_DATARATE_11AX80_36MBPS_1GI_NSS2_DCM 0x88c0 -#define FAPI_DATARATE_11AX80_72M1BPS_1GI_NSS2_DCM 0x88c1 -#define FAPI_DATARATE_11AX80_144M1BPS_1GI_NSS2_DCM 0x88c3 -#define FAPI_DATARATE_11AX80_216M2BPS_1GI_NSS2_DCM 0x88c4 -#define FAPI_DATARATE_11AX80_34MBPS_2GI_NSS2_DCM 0x88d0 -#define FAPI_DATARATE_11AX80_68M1BPS_2GI_NSS2_DCM 0x88d1 -#define FAPI_DATARATE_11AX80_136M1BPS_2GI_NSS2_DCM 0x88d3 -#define FAPI_DATARATE_11AX80_204M2BPS_2GI_NSS2_DCM 0x88d4 -#define FAPI_DATARATE_11AX80_30M6BPS_4GI_NSS2_DCM 0x88e0 -#define FAPI_DATARATE_11AX80_61M3BPS_4GI_NSS2_DCM 0x88e1 -#define FAPI_DATARATE_11AX80_122M5BPS_4GI_NSS2_DCM 0x88e3 -#define FAPI_DATARATE_11AX80_183M8BPS_4GI_NSS2_DCM 0x88e4 -#define FAPI_DATARATE_11AX160_72M1BPS_1GI 0x8c00 -#define FAPI_DATARATE_11AX160_144M1BPS_1GI 0x8c01 -#define FAPI_DATARATE_11AX160_216M2BPS_1GI 0x8c02 -#define FAPI_DATARATE_11AX160_288M2BPS_1GI 0x8c03 -#define FAPI_DATARATE_11AX160_432M4BPS_1GI 0x8c04 -#define FAPI_DATARATE_11AX160_576M5BPS_1GI 0x8c05 -#define FAPI_DATARATE_11AX160_648M5BPS_1GI 0x8c06 -#define FAPI_DATARATE_11AX160_720M6BPS_1GI 0x8c07 -#define FAPI_DATARATE_11AX160_864M7BPS_1GI 0x8c08 -#define FAPI_DATARATE_11AX160_960M7BPS_1GI 0x8c09 -#define FAPI_DATARATE_11AX160_1080M9BPS_1GI 0x8c0a -#define FAPI_DATARATE_11AX160_1201MBPS_1GI 0x8c0b -#define FAPI_DATARATE_11AX160_68M1BPS_2GI 0x8c10 -#define FAPI_DATARATE_11AX160_136M1BPS_2GI 0x8c11 -#define FAPI_DATARATE_11AX160_204M2BPS_2GI 0x8c12 -#define FAPI_DATARATE_11AX160_272M2BPS_2GI 0x8c13 -#define FAPI_DATARATE_11AX160_408M3BPS_2GI 0x8c14 -#define FAPI_DATARATE_11AX160_544M4BPS_2GI 0x8c15 -#define FAPI_DATARATE_11AX160_612M5BPS_2GI 0x8c16 -#define FAPI_DATARATE_11AX160_680M6BPS_2GI 0x8c17 -#define FAPI_DATARATE_11AX160_816M7BPS_2GI 0x8c18 -#define FAPI_DATARATE_11AX160_907M4BPS_2GI 0x8c19 -#define FAPI_DATARATE_11AX160_1020M8BPS_2GI 0x8c1a -#define FAPI_DATARATE_11AX160_1134M2BPS_2GI 0x8c1b -#define FAPI_DATARATE_11AX160_61M3BPS_4GI 0x8c20 -#define FAPI_DATARATE_11AX160_122M5BPS_4GI 0x8c21 -#define FAPI_DATARATE_11AX160_183M8BPS_4GI 0x8c22 -#define FAPI_DATARATE_11AX160_245MBPS_4GI 0x8c23 -#define FAPI_DATARATE_11AX160_367M5BPS_4GI 0x8c24 -#define FAPI_DATARATE_11AX160_490MBPS_4GI 0x8c25 -#define FAPI_DATARATE_11AX160_551M3BPS_4GI 0x8c26 -#define FAPI_DATARATE_11AX160_612M5BPS_4GI 0x8c27 -#define FAPI_DATARATE_11AX160_735MBPS_4GI 0x8c28 -#define FAPI_DATARATE_11AX160_816M6BPS_4GI 0x8c29 -#define FAPI_DATARATE_11AX160_918M8BPS_4GI 0x8c2a -#define FAPI_DATARATE_11AX160_1020M8BPS_4GI 0x8c2b -#define FAPI_DATARATE_11AX160_36MBPS_1GI_DCM 0x8c40 -#define FAPI_DATARATE_11AX160_72M1BPS_1GI_DCM 0x8c41 -#define FAPI_DATARATE_11AX160_144M1BPS_1GI_DCM 0x8c43 -#define FAPI_DATARATE_11AX160_216M2BPS_1GI_DCM 0x8c44 -#define FAPI_DATARATE_11AX160_34MBPS_2GI_DCM 0x8c50 -#define FAPI_DATARATE_11AX160_68M1BPS_2GI_DCM 0x8c51 -#define FAPI_DATARATE_11AX160_136M1BPS_2GI_DCM 0x8c53 -#define FAPI_DATARATE_11AX160_204M2BPS_2GI_DCM 0x8c54 -#define FAPI_DATARATE_11AX160_30M6BPS_4GI_DCM 0x8c60 -#define FAPI_DATARATE_11AX160_61M3BPS_4GI_DCM 0x8c61 -#define FAPI_DATARATE_11AX160_122M5BPS_4GI_DCM 0x8c63 -#define FAPI_DATARATE_11AX160_183M8BPS_4GI_DCM 0x8c64 -#define FAPI_DATARATE_11AX160_144M1BPS_1GI_NSS2 0x8c80 -#define FAPI_DATARATE_11AX160_288M2BPS_1GI_NSS2 0x8c81 -#define FAPI_DATARATE_11AX160_432M4BPS_1GI_NSS2 0x8c82 -#define FAPI_DATARATE_11AX160_576M5BPS_1GI_NSS2 0x8c83 -#define FAPI_DATARATE_11AX160_864M7BPS_1GI_NSS2 0x8c84 -#define FAPI_DATARATE_11AX160_1152M9BPS_1GI_NSS2 0x8c85 -#define FAPI_DATARATE_11AX160_1297M1BPS_1GI_NSS2 0x8c86 -#define FAPI_DATARATE_11AX160_1441M2BPS_1GI_NSS2 0x8c87 -#define FAPI_DATARATE_11AX160_1729M4BPS_1GI_NSS2 0x8c88 -#define FAPI_DATARATE_11AX160_1921M5BPS_1GI_NSS2 0x8c89 -#define FAPI_DATARATE_11AX160_2161M8BPS_1GI_NSS2 0x8c8a -#define FAPI_DATARATE_11AX160_2401M9BPS_1GI_NSS2 0x8c8b -#define FAPI_DATARATE_11AX160_136M1BPS_2GI_NSS2 0x8c90 -#define FAPI_DATARATE_11AX160_272M2BPS_2GI_NSS2 0x8c91 -#define FAPI_DATARATE_11AX160_408M3BPS_2GI_NSS2 0x8c92 -#define FAPI_DATARATE_11AX160_544M4BPS_2GI_NSS2 0x8c93 -#define FAPI_DATARATE_11AX160_816M7BPS_2GI_NSS2 0x8c94 -#define FAPI_DATARATE_11AX160_1088M9BPS_2GI_NSS2 0x8c95 -#define FAPI_DATARATE_11AX160_1225MBPS_2GI_NSS2 0x8c96 -#define FAPI_DATARATE_11AX160_1361M1BPS_2GI_NSS2 0x8c97 -#define FAPI_DATARATE_11AX160_1633M3BPS_2GI_NSS2 0x8c98 -#define FAPI_DATARATE_11AX160_1814M8BPS_2GI_NSS2 0x8c99 -#define FAPI_DATARATE_11AX160_2041M7BPS_2GI_NSS2 0x8c9a -#define FAPI_DATARATE_11AX160_2268M5BPS_2GI_NSS2 0x8c9b -#define FAPI_DATARATE_11AX160_122M5BPS_4GI_NSS2 0x8ca0 -#define FAPI_DATARATE_11AX160_245MBPS_4GI_NSS2 0x8ca1 -#define FAPI_DATARATE_11AX160_367M5BPS_4GI_NSS2 0x8ca2 -#define FAPI_DATARATE_11AX160_490MBPS_4GI_NSS2 0x8ca3 -#define FAPI_DATARATE_11AX160_735MBPS_4GI_NSS2 0x8ca4 -#define FAPI_DATARATE_11AX160_980MBPS_4GI_NSS2 0x8ca5 -#define FAPI_DATARATE_11AX160_1102M5BPS_4GI_NSS2 0x8ca6 -#define FAPI_DATARATE_11AX160_1225MBPS_4GI_NSS2 0x8ca7 -#define FAPI_DATARATE_11AX160_1470MBPS_4GI_NSS2 0x8ca8 -#define FAPI_DATARATE_11AX160_1633M3BPS_4GI_NSS2 0x8ca9 -#define FAPI_DATARATE_11AX160_1837M5BPS_4GI_NSS2 0x8caa -#define FAPI_DATARATE_11AX160_2041M6BPS_4GI_NSS2 0x8cab -#define FAPI_DATARATE_11AX160_72M1BPS_1GI_NSS2_DCM 0x8cc0 -#define FAPI_DATARATE_11AX160_144M1BPS_1GI_NSS2_DCM 0x8cc1 -#define FAPI_DATARATE_11AX160_288M2BPS_1GI_NSS2_DCM 0x8cc3 -#define FAPI_DATARATE_11AX160_432M4BPS_1GI_NSS2_DCM 0x8cc4 -#define FAPI_DATARATE_11AX160_68M1BPS_2GI_NSS2_DCM 0x8cd0 -#define FAPI_DATARATE_11AX160_136M1BPS_2GI_NSS2_DCM 0x8cd1 -#define FAPI_DATARATE_11AX160_272M2BPS_2GI_NSS2_DCM 0x8cd3 -#define FAPI_DATARATE_11AX160_408M3BPS_2GI_NSS2_DCM 0x8cd4 -#define FAPI_DATARATE_11AX160_61M3BPS_4GI_NSS2_DCM 0x8ce0 -#define FAPI_DATARATE_11AX160_122M5BPS_4GI_NSS2_DCM 0x8ce1 -#define FAPI_DATARATE_11AX160_245MBPS_4GI_NSS2_DCM 0x8ce3 -#define FAPI_DATARATE_11AX160_367M5BPS_4GI_NSS2_DCM 0x8ce4 -#define FAPI_DATARATE_CTR_TOTAL 0xe000 -#define FAPI_DATARATE_CTR_NO_ERROR 0xe001 -#define FAPI_DATARATE_CTR_CRC_ERROR 0xe002 -#define FAPI_DATARATE_CTR_BAD_SIGNAL 0xe003 -#define FAPI_DATARATE_CTR_STBC 0xe004 -#define FAPI_DATARATE_CTR_DUPLICATE 0xe005 -#define FAPI_DATARATE_CTR_ERROR 0xe006 -#define FAPI_DATARATE_CTR_LDPC 0xe007 -#define FAPI_DATARATE_CTR_BEAMFORMED 0xe008 - -#define FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME 0x0000 -#define FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME 0x0001 -#define FAPI_DATAUNITDESCRIPTOR_AMSDU_SUBFRAME 0x0002 -#define FAPI_DATAUNITDESCRIPTOR_AMSDU 0x0003 -#define FAPI_DATAUNITDESCRIPTOR_TCP_ACK 0x0004 - -#define FAPI_DEVICEROLE_INFRASTRUCTURE_STATION 0x0001 -#define FAPI_DEVICEROLE_P2P_GO 0x0002 -#define FAPI_DEVICEROLE_P2P_DEVICE 0x0003 -#define FAPI_DEVICEROLE_P2P_CLIENT 0x0004 - -#define FAPI_DEVICESTATE_IDLE 0 -#define FAPI_DEVICESTATE_RX_RUNNING 1 -#define FAPI_DEVICESTATE_TX_RUNNING 2 -#define FAPI_DEVICESTATE_CW_RUNNING 3 -#define FAPI_DEVICESTATE_BIST_RUNNING 4 - -#define FAPI_DFSREGULATORY_UNKNOWN 0x0000 -#define FAPI_DFSREGULATORY_FCC 0x0001 -#define FAPI_DFSREGULATORY_ETSI 0x0002 -#define FAPI_DFSREGULATORY_JAPAN 0x0003 -#define FAPI_DFSREGULATORY_GLOBAL 0x0004 -#define FAPI_DFSREGULATORY_CHINA 0x0006 - -#define FAPI_DIRECTION_TRANSMIT 0x0000 -#define FAPI_DIRECTION_RECEIVE 0x0001 - -#define FAPI_ENDPOINT_HOSTIO 0x0001 -#define FAPI_ENDPOINT_DPLP 0x0002 - -#define FAPI_EPNOPOLICY_HIDDEN 0x0001 -#define FAPI_EPNOPOLICY_A_BAND 0x0002 -#define FAPI_EPNOPOLICY_G_BAND 0x0004 -#define FAPI_EPNOPOLICY_STRICT_MATCH 0x0008 -#define FAPI_EPNOPOLICY_SAME_NETWORK 0x0010 -#define FAPI_EPNOPOLICY_AUTH_OPEN 0x0100 -#define FAPI_EPNOPOLICY_AUTH_PSK 0x0200 -#define FAPI_EPNOPOLICY_AUTH_EAPOL 0x0400 - -#define FAPI_EVENT_WIFI_EVENT_ASSOCIATION_REQUESTED 0x0000 -#define FAPI_EVENT_WIFI_EVENT_AUTH_COMPLETE 0x0001 -#define FAPI_EVENT_WIFI_EVENT_ASSOC_COMPLETE 0x0002 -#define FAPI_EVENT_WIFI_EVENT_FW_AUTH_STARTED 0x0003 -#define FAPI_EVENT_WIFI_EVENT_FW_ASSOC_STARTED 0x0004 -#define FAPI_EVENT_WIFI_EVENT_FW_RE_ASSOC_STARTED 0x0005 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_SCAN_REQUESTED 0x0006 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND 0x0007 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_SCAN_COMPLETE 0x0008 -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_STARTED 0x0009 -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_COMPLETE 0x000a -#define FAPI_EVENT_WIFI_EVENT_DISASSOCIATION_REQUESTED 0x000b -#define FAPI_EVENT_WIFI_EVENT_RE_ASSOCIATION_REQUESTED 0x000c -#define FAPI_EVENT_WIFI_EVENT_ROAM_REQUESTED 0x000d -#define FAPI_EVENT_WIFI_EVENT_BEACON_RECEIVED 0x000e -#define FAPI_EVENT_WIFI_EVENT_ROAM_SCAN_STARTED 0x000f -#define FAPI_EVENT_WIFI_EVENT_ROAM_SCAN_COMPLETE 0x0010 -#define FAPI_EVENT_WIFI_EVENT_ROAM_SEARCH_STARTED 0x0011 -#define FAPI_EVENT_WIFI_EVENT_ROAM_SEARCH_STOPPED 0x0012 -#define FAPI_EVENT_WIFI_EVENT_CHANNEL_SWITCH_ANOUNCEMENT 0x0014 -#define FAPI_EVENT_WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START 0x0015 -#define FAPI_EVENT_WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP 0x0016 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED 0x0017 -#define FAPI_EVENT_WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED 0x0018 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED 0x001a -#define FAPI_EVENT_WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE 0x001b -#define FAPI_EVENT_WIFI_EVENT_BT_COEX_BT_SCO_START 0x001c -#define FAPI_EVENT_WIFI_EVENT_BT_COEX_BT_SCO_STOP 0x001d -#define FAPI_EVENT_WIFI_EVENT_BT_COEX_BT_SCAN_START 0x001e -#define FAPI_EVENT_WIFI_EVENT_BT_COEX_BT_SCAN_STOP 0x001f -#define FAPI_EVENT_WIFI_EVENT_BT_COEX_BT_HID_START 0x0020 -#define FAPI_EVENT_WIFI_EVENT_BT_COEX_BT_HID_STOP 0x0021 -#define FAPI_EVENT_WIFI_EVENT_ROAM_AUTH_STARTED 0x0022 -#define FAPI_EVENT_WIFI_EVENT_ROAM_AUTH_COMPLETE 0x0023 -#define FAPI_EVENT_WIFI_EVENT_ROAM_ASSOC_STARTED 0x0024 -#define FAPI_EVENT_WIFI_EVENT_ROAM_ASSOC_COMPLETE 0x0025 -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_STOP 0x0026 -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_CYCLE_STARTED 0x0027 -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_CYCLE_COMPLETED 0x0028 -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_BUCKET_STARTED 0x0029 -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_BUCKET_COMPLETED 0x002a -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_RESULTS_AVAILABLE 0x002b -#define FAPI_EVENT_WIFI_EVENT_G_SCAN_CAPABILITIES 0x002c -#define FAPI_EVENT_WIFI_EVENT_ROAM_CANDIDATE_FOUND 0x002d -#define FAPI_EVENT_WIFI_EVENT_ROAM_SCAN_CONFIG 0x002e -#define FAPI_EVENT_WIFI_EVENT_AUTH_TIMEOUT 0x002f -#define FAPI_EVENT_WIFI_EVENT_ASSOC_TIMEOUT 0x0030 -#define FAPI_EVENT_WIFI_EVENT_MEM_ALLOC_FAILURE 0x0031 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_PNO_ADD 0x0032 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_PNO_REMOVE 0x0033 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND 0x0034 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED 0x0035 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND 0x0036 -#define FAPI_EVENT_WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE 0x0037 -#define FAPI_EVENT_WIFI_EVENT_BLACKOUT_START 0x0064 -#define FAPI_EVENT_WIFI_EVENT_BLACKOUT_STOP 0x0065 -#define FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED 0x0100 -#define FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED 0x0101 -#define FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED 0x0102 -#define FAPI_EVENT_WIFI_EVENT_NAN_ADDRESS_CHANGED 0x0103 -#define FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_STARTED 0x0104 -#define FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_JOINED 0x0105 -#define FAPI_EVENT_WIFI_EVENT_NAN_TRANSMIT_FOLLOWUP 0x0106 - -#define FAPI_HIDDENSSID_NOT_HIDDEN 0x0000 -#define FAPI_HIDDENSSID_HIDDEN_ZERO_LENGTH 0x0001 -#define FAPI_HIDDENSSID_HIDDEN_ZERO_DATA 0x0002 - -#define FAPI_HT_NON_HT_RATE 0x1 -#define FAPI_HT_HT_RATE 0x2 -#define FAPI_HT_VHT_RATE 0x3 - -#define FAPI_KEYTYPE_GROUP 0x0000 -#define FAPI_KEYTYPE_PAIRWISE 0x0001 -#define FAPI_KEYTYPE_WEP 0x0002 -#define FAPI_KEYTYPE_IGTK 0x0003 -#define FAPI_KEYTYPE_PMK 0x0004 -#define FAPI_KEYTYPE_FIRST_ILLEGAL 0x0005 - -#define FAPI_MESSAGETYPE_EAP_MESSAGE 0x0001 -#define FAPI_MESSAGETYPE_EAPOL_KEY_M123 0x0002 -#define FAPI_MESSAGETYPE_EAPOL_KEY_M4 0x0003 -#define FAPI_MESSAGETYPE_ARP 0x0004 -#define FAPI_MESSAGETYPE_DHCP 0x0005 -#define FAPI_MESSAGETYPE_NEIGHBOR_DISCOVERY 0x0006 -#define FAPI_MESSAGETYPE_WAI_MESSAGE 0x0007 -#define FAPI_MESSAGETYPE_ANY_OTHER 0x0008 -#define FAPI_MESSAGETYPE_IEEE80211_ACTION 0x0010 -#define FAPI_MESSAGETYPE_IEEE80211_MGMT 0x0011 - -#define FAPI_MODE_SOURCE 0x0001 -#define FAPI_MODE_SINK 0x0002 -#define FAPI_MODE_LOOPBACK 0x0003 - -#define FAPI_NANAVAILABILITYDURATION_16MS 0x00 -#define FAPI_NANAVAILABILITYDURATION_32MS 0x01 -#define FAPI_NANAVAILABILITYDURATION_64MS 0x02 - -#define FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT 0x0002 -#define FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT 0x0004 -#define FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT 0x0008 - -#define FAPI_NANSDFCONTROL_PUBLISH_END_EVENT 0x0001 -#define FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT 0x0002 -#define FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT 0x0004 -#define FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT 0x0008 -#define FAPI_NANSDFCONTROL_FOLLOWUP_TRANSMIT_STATUS 0x0010 - -#define FAPI_PACKETFILTERMODE_OPT_OUT 0x01 -#define FAPI_PACKETFILTERMODE_OPT_IN 0x02 -#define FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP 0x04 -#define FAPI_PACKETFILTERMODE_OPT_IN_SLEEP 0x08 - -#define FAPI_PMALLOCAREA_PMALLOC_STATS 0x0000 -#define FAPI_PMALLOCAREA_PMALLOC_FSM_STATS 0x0001 -#define FAPI_PMALLOCAREA_HOSTIO_SIG_SIZES 0x0002 - -#define FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE 0x0000 -#define FAPI_POWERMANAGEMENTMODE_POWER_SAVE 0x0001 - -#define FAPI_PRIMARYCHANNELPOSITION_P0 0x00 -#define FAPI_PRIMARYCHANNELPOSITION_P1 0x01 -#define FAPI_PRIMARYCHANNELPOSITION_P2 0x02 -#define FAPI_PRIMARYCHANNELPOSITION_P3 0x03 -#define FAPI_PRIMARYCHANNELPOSITION_P4 0x04 -#define FAPI_PRIMARYCHANNELPOSITION_P5 0x05 -#define FAPI_PRIMARYCHANNELPOSITION_P6 0x06 -#define FAPI_PRIMARYCHANNELPOSITION_P7 0x07 -#define FAPI_PRIMARYCHANNELPOSITION_NOT_APPLICABLE 0x08 - -#define FAPI_PRIORITY_QOS_UP0 0x0000 -#define FAPI_PRIORITY_QOS_UP1 0x0001 -#define FAPI_PRIORITY_QOS_UP2 0x0002 -#define FAPI_PRIORITY_QOS_UP3 0x0003 -#define FAPI_PRIORITY_QOS_UP4 0x0004 -#define FAPI_PRIORITY_QOS_UP5 0x0005 -#define FAPI_PRIORITY_QOS_UP6 0x0006 -#define FAPI_PRIORITY_QOS_UP7 0x0007 -#define FAPI_PRIORITY_CONTENTION 0x8000 - -#define FAPI_PROCEDURETYPE_UNKNOWN 0x0000 -#define FAPI_PROCEDURETYPE_CONNECTION_STARTED 0x0001 -#define FAPI_PROCEDURETYPE_DEVICE_DISCOVERED 0x0002 -#define FAPI_PROCEDURETYPE_ROAMING_STARTED 0x0003 - -#define FAPI_PROCESSOR_DEFAULT 0x0 -#define FAPI_PROCESSOR_CHIPCPU 0x1 -#define FAPI_PROCESSOR_HOSTCPU 0x3 - -#define FAPI_PROTOCOL_UDP 0x0001 -#define FAPI_PROTOCOL_TCP 0x0002 - -#define FAPI_PURPOSE_BEACON 0x0001 -#define FAPI_PURPOSE_PROBE_RESPONSE 0x0002 -#define FAPI_PURPOSE_ASSOCIATION_RESPONSE 0x0004 -#define FAPI_PURPOSE_LOCAL 0x0008 -#define FAPI_PURPOSE_ASSOCIATION_REQUEST 0x0010 -#define FAPI_PURPOSE_PROBE_REQUEST 0x0020 - -#define FAPI_RADIOBITMAP_RADIO_0 0x0001 -#define FAPI_RADIOBITMAP_RADIO_1 0x0002 - -#define FAPI_RANGINGINDTYPE_CONTINUOUS_INDICATION 0x0001 -#define FAPI_RANGINGINDTYPE_INGRESS 0x0002 -#define FAPI_RANGINGINDTYPE_EGRESS 0x0004 - -#define FAPI_REASONCODE_RESERVED 0x0000 -#define FAPI_REASONCODE_UNSPECIFIED_REASON 0x0001 -#define FAPI_REASONCODE_DEAUTHENTICATED_INVALID_AUTHENTICATION 0x0002 -#define FAPI_REASONCODE_DEAUTHENTICATED_LEAVING 0x0003 -#define FAPI_REASONCODE_DEAUTHENTICATED_NO_MORE_STATIONS 0x0005 -#define FAPI_REASONCODE_DEAUTHENTICATED_INVALID_CLASS_2_FRAME 0x0006 -#define FAPI_REASONCODE_DEAUTHENTICATED_INVALID_CLASS_3_FRAME 0x0007 -#define FAPI_REASONCODE_DEAUTHENTICATED_REASON_INVALID_IE 0x000d -#define FAPI_REASONCODE_DEAUTHENTICATED_4_WAY_HANDSHAKE_TIMEOUT 0x000f -#define FAPI_REASONCODE_DEAUTHENTICATED_GROUP_HANDSHAKE_TIMEOUT 0x0010 -#define FAPI_REASONCODE_DEAUTHENTICATED_HANDSHAKE_ELEMENT_MISMATCH 0x0011 -#define FAPI_REASONCODE_DEAUTHENTICATED_REASON_INVALID_RSNE 0x0014 -#define FAPI_REASONCODE_DEAUTHENTICATED_802_1_X_AUTH_FAILED 0x0017 -#define FAPI_REASONCODE_TDLS_PEER_UNREACHABLE 0x0019 -#define FAPI_REASONCODE_TDLS_TEARDOWN_UNSPECIFIED_REASON 0x001a -#define FAPI_REASONCODE_QOS_UNSPECIFIED_REASON 0x0020 -#define FAPI_REASONCODE_QOS_EXCESSIVE_NOT_ACK 0x0022 -#define FAPI_REASONCODE_QOS_TXOP_LIMIT_EXCEEDED 0x0023 -#define FAPI_REASONCODE_QSTA_LEAVING 0x0024 -#define FAPI_REASONCODE_END 0x0025 -#define FAPI_REASONCODE_UNKNOWN 0x0026 -#define FAPI_REASONCODE_TIMEOUT 0x0027 -#define FAPI_REASONCODE_KEEP_ALIVE_FAILURE 0x0028 -#define FAPI_REASONCODE_START 0x0029 -#define FAPI_REASONCODE_DEAUTHENTICATED_REASON_INVALID_PMKID 0x0031 -#define FAPI_REASONCODE_INVALID_PMKID 0x0049 -#define FAPI_REASONCODE_SYNCHRONISATION_LOSS 0x8003 -#define FAPI_REASONCODE_SECURITY_REQUIRED 0x8004 -#define FAPI_REASONCODE_ROAMING_FAILURE_LINK_LOSS_NO_CANDIDATE 0x8005 -#define FAPI_REASONCODE_HOTSPOT_MAX_CLIENT_REACHED 0x8006 -#define FAPI_REASONCODE_CHANNEL_SWITCH_FAILURE 0x8007 -#define FAPI_REASONCODE_REPORTING_ABORTED_SCANNING 0x8008 -#define FAPI_REASONCODE_REPORTING_ABORTED_ROAMING 0x8009 -#define FAPI_REASONCODE_NAN_SERVICE_TERMINATED_TIMEOUT 0x9001 -#define FAPI_REASONCODE_NAN_SERVICE_TERMINATED_USER_REQUEST 0x9002 -#define FAPI_REASONCODE_NAN_SERVICE_TERMINATED_COUNT_REACHED 0x9003 -#define FAPI_REASONCODE_NAN_SERVICE_TERMINATED_DISCOVERY_SHUTDOWN 0x9004 -#define FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_SUCCESS 0x9006 -#define FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_FAILURE 0x9007 -#define FAPI_REASONCODE_NDP_ACCEPTED 0x9008 -#define FAPI_REASONCODE_NDP_REJECTED 0x9009 - -#define FAPI_REPORTMODE_RESERVED 0x0001 -#define FAPI_REPORTMODE_END_OF_SCAN_CYCLE 0x0002 -#define FAPI_REPORTMODE_REAL_TIME 0x0004 -#define FAPI_REPORTMODE_NO_BATCH 0x0008 - -#define FAPI_RESULTCODE_SUCCESS 0x0000 -#define FAPI_RESULTCODE_UNSPECIFIED_FAILURE 0x0001 -#define FAPI_RESULTCODE_INVALID_PARAMETERS 0x0026 -#define FAPI_RESULTCODE_REJECTED_INVALID_IE 0x0028 -#define FAPI_RESULTCODE_NOT_ALLOWED 0x0030 -#define FAPI_RESULTCODE_NOT_PRESENT 0x0031 -#define FAPI_RESULTCODE_TRANSMISSION_FAILURE 0x004f -#define FAPI_RESULTCODE_TOO_MANY_SIMULTANEOUS_REQUESTS 0x8001 -#define FAPI_RESULTCODE_BSS_ALREADY_STARTED_OR_JOINED 0x8002 -#define FAPI_RESULTCODE_NOT_SUPPORTED 0x8003 -#define FAPI_RESULTCODE_INVALID_STATE 0x8004 -#define FAPI_RESULTCODE_INSUFFICIENT_RESOURCE 0x8006 -#define FAPI_RESULTCODE_INVALID_VIRTUAL_INTERFACE_INDEX 0x800a -#define FAPI_RESULTCODE_HOST_REQUEST_SUCCESS 0x800b -#define FAPI_RESULTCODE_HOST_REQUEST_FAILED 0x800c -#define FAPI_RESULTCODE_INVALID_FREQUENCY 0x800e -#define FAPI_RESULTCODE_PROBE_TIMEOUT 0x800f -#define FAPI_RESULTCODE_AUTH_TIMEOUT 0x8010 -#define FAPI_RESULTCODE_ASSOC_TIMEOUT 0x8011 -#define FAPI_RESULTCODE_ASSOC_ABORT 0x8012 -#define FAPI_RESULTCODE_AUTH_NO_ACK 0x8013 -#define FAPI_RESULTCODE_ASSOC_NO_ACK 0x8014 -#define FAPI_RESULTCODE_AUTH_FAILED_CODE 0x8100 -#define FAPI_RESULTCODE_ASSOC_FAILED_CODE 0x8200 -#define FAPI_RESULTCODE_INVALID_TLV_VALUE 0x9000 -#define FAPI_RESULTCODE_NAN_PROTOCOL_FAILURE 0x9001 -#define FAPI_RESULTCODE_NAN_INVALID_PUBLISH_SUBSCRIBE_ID 0x9002 -#define FAPI_RESULTCODE_NAN_INVALID_REQUESTOR_INSTANCE_ID 0x9003 -#define FAPI_RESULTCODE_UNSUPPORTED_CONCURRENCY 0x9004 -#define FAPI_RESULTCODE_NAN_INVALID_NDP_ID 0x9005 -#define FAPI_RESULTCODE_NAN_INVALID_MATCH_ID 0x9006 -#define FAPI_RESULTCODE_NAN_NO_OTA_ACK 0x9007 -#define FAPI_RESULTCODE_NAN_INVALID_AVAILABILITY 0x9008 -#define FAPI_RESULTCODE_NAN_IMMUTABLE_UNACCEPTABLE 0x9009 -#define FAPI_RESULTCODE_NAN_REJECTED_SECURITY_POLICY 0x900a -#define FAPI_RESULTCODE_NDP_REJECTED 0x900b -#define FAPI_RESULTCODE_NDL_UNACCEPTABLE 0x900c -#define FAPI_RESULTCODE_NDL_FAILED_SCHEDULE 0x900d - -#define FAPI_RTTBANDWIDTH_20MHZ 0x0004 -#define FAPI_RTTBANDWIDTH_40MHZ 0x0008 -#define FAPI_RTTBANDWIDTH_80MHZ 0x0010 -#define FAPI_RTTBANDWIDTH_160MHZ 0x0020 - -#define FAPI_RTTPREAMBLE_LEGACY 0x0001 -#define FAPI_RTTPREAMBLE_HT 0x0002 -#define FAPI_RTTPREAMBLE_VHT 0x0004 - -#define FAPI_RTTSTATUS_SUCCESS 0x0000 -#define FAPI_RTTSTATUS_UNSPECIFIED_FAILURE 0x0001 -#define FAPI_RTTSTATUS_FAIL_NO_RESPONSE 0x0002 -#define FAPI_RTTSTATUS_FAIL_REJECTED 0x0003 -#define FAPI_RTTSTATUS_FAIL_NOT_SCHEDULED 0x0004 -#define FAPI_RTTSTATUS_FAIL_TIMEOUT 0x0005 -#define FAPI_RTTSTATUS_FAIL_INCORRECT_CHANNEL 0x0006 -#define FAPI_RTTSTATUS_FAIL_FTM_NOT_SUPPORTED 0x0007 -#define FAPI_RTTSTATUS_FAIL_MEASUREMENT_ABORTED 0x0008 -#define FAPI_RTTSTATUS_FAIL_INVALID_TIME_STAMP 0x0009 -#define FAPI_RTTSTATUS_FAIL_NO_FTM_RECEIVED 0x000a -#define FAPI_RTTSTATUS_FAIL_BURST_NOT_SCHEDULED 0x000b -#define FAPI_RTTSTATUS_FAIL_BUSY_TRY_LATER 0x000c -#define FAPI_RTTSTATUS_FAIL_INVALID_REQUEST 0x000d -#define FAPI_RTTSTATUS_FAIL_FTM_PARAMETER_OVERRIDE 0x000f - -#define FAPI_RTTTYPE_ONE_SIDED 0x0001 -#define FAPI_RTTTYPE_TWO_SIDED 0x0002 - -#define FAPI_RULEFLAG_NO_IR 0x0001 -#define FAPI_RULEFLAG_DFS 0x0002 -#define FAPI_RULEFLAG_NO_OFDM 0x0004 -#define FAPI_RULEFLAG_NO_INDOOR 0x0008 -#define FAPI_RULEFLAG_NO_OUTDOOR 0x0010 - -#define FAPI_RXSTARTFLAGS_NONE 0x0000 -#define FAPI_RXSTARTFLAGS_SCAN_CHANNEL 0x0001 -#define FAPI_RXSTARTFLAGS_FILTERING 0x0002 -#define FAPI_RXSTARTFLAGS_BEAMFORMING 0x0004 -#define FAPI_RXSTARTFLAGS_ACK 0x0008 -#define FAPI_RXSTARTFLAGS_LP_MODE 0x0010 -#define FAPI_RXSTARTFLAGS_CHAN_RSSI 0x0020 -#define FAPI_RXSTARTFLAGS_DISABLE_EXTERNAL_LNA 0x0040 - -#define FAPI_SCANPOLICY_PASSIVE 0x01 -#define FAPI_SCANPOLICY_TEST_MODE 0x02 -#define FAPI_SCANPOLICY_ANY_RA 0x04 -#define FAPI_SCANPOLICY_2_4GHZ 0x08 -#define FAPI_SCANPOLICY_5GHZ 0x10 -#define FAPI_SCANPOLICY_NON_DFS 0x20 -#define FAPI_SCANPOLICY_DFS 0x40 -#define FAPI_SCANPOLICY_ON_CHANNEL 0x80 - -#define FAPI_SCANTYPE_INITIAL_SCAN 0x0001 -#define FAPI_SCANTYPE_FULL_SCAN 0x0002 -#define FAPI_SCANTYPE_SCHEDULED_SCAN 0x0003 -#define FAPI_SCANTYPE_P2P_SCAN_FULL 0x0004 -#define FAPI_SCANTYPE_P2P_SCAN_SOCIAL 0x0005 -#define FAPI_SCANTYPE_OBSS_SCAN 0x0006 -#define FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION 0x0007 -#define FAPI_SCANTYPE_GSCAN 0x0009 -#define FAPI_SCANTYPE_MEASUREMENT_SCAN 0x000a -#define FAPI_SCANTYPE_SOFT_NEIGHBOUR_ROAMING_SCAN 0x000b -#define FAPI_SCANTYPE_SOFT_CACHED_ROAMING_SCAN 0x000c -#define FAPI_SCANTYPE_SOFT_ALL_ROAMING_SCAN 0x000d -#define FAPI_SCANTYPE_HARD_NEIGHBOUR_ROAMING_SCAN 0x000e -#define FAPI_SCANTYPE_HARD_CACHED_ROAMING_SCAN 0x000f -#define FAPI_SCANTYPE_HARD_ALL_ROAMING_SCAN 0x0010 -#define FAPI_SCANTYPE_OBSS_SCAN_INTERNAL 0x0011 -#define FAPI_SCANTYPE_NAN_SCAN 0x0012 -#define FAPI_SCANTYPE_FTM_NEIGHBOUR_SCAN 0x0013 -#define FAPI_SCANTYPE_FIRST_ILLEGAL 0x0014 - -#define FAPI_STATSSTOPBITMAP_STATS_RADIO 0x0001 -#define FAPI_STATSSTOPBITMAP_STATS_RADIO_CCA 0x0002 -#define FAPI_STATSSTOPBITMAP_STATS_RADIO_CHANNELS 0x0004 -#define FAPI_STATSSTOPBITMAP_STATS_RADIO_SCAN 0x0008 -#define FAPI_STATSSTOPBITMAP_STATS_IFACE 0x0010 -#define FAPI_STATSSTOPBITMAP_STATS_IFACE_TXRATE 0x0020 -#define FAPI_STATSSTOPBITMAP_STATS_IFACE_AC 0x0040 -#define FAPI_STATSSTOPBITMAP_STATS_IFACE_CONTENSION 0x0080 - -#define FAPI_TDLSACTION_DISCOVERY 0x0000 -#define FAPI_TDLSACTION_SETUP 0x0001 -#define FAPI_TDLSACTION_TEARDOWN 0x0002 - -#define FAPI_TDLSEVENT_CONNECTED 0x0001 -#define FAPI_TDLSEVENT_DISCONNECTED 0x0002 -#define FAPI_TDLSEVENT_DISCOVERED 0x0003 - -#define FAPI_TRANSMISSIONSTATUS_SUCCESSFUL 0x0000 -#define FAPI_TRANSMISSIONSTATUS_RETRY_LIMIT 0x0001 -#define FAPI_TRANSMISSIONSTATUS_TX_LIFETIME 0x0002 -#define FAPI_TRANSMISSIONSTATUS_NO_BSS 0x0003 -#define FAPI_TRANSMISSIONSTATUS_EXCESSIVE_DATA_LENGTH 0x0004 -#define FAPI_TRANSMISSIONSTATUS_UNAVAILABLE_KEY_MAPPING 0x0005 -#define FAPI_TRANSMISSIONSTATUS_UNSPECIFIED_FAILURE 0x0006 - -#define FAPI_TXDATATYPE_DATA_WORD 0x0000 -#define FAPI_TXDATATYPE_DATA_RANDOM 0x0001 - -#define FAPI_TXREADFLAGS_NONE 0x0000 -#define FAPI_TXREADFLAGS_FRAME_COUNTING 0x0001 -#define FAPI_TXREADFLAGS_THERMAL_CUTOUT 0x0002 - -#define FAPI_TXSETPARAMSFLAGS_NONE 0x0000 -#define FAPI_TXSETPARAMSFLAGS_ACK 0x0001 -#define FAPI_TXSETPARAMSFLAGS_DUPLICATE_80 0x0002 -#define FAPI_TXSETPARAMSFLAGS_DUPLICATE_40 0x0004 -#define FAPI_TXSETPARAMSFLAGS_DEAFEN_RX 0x0008 -#define FAPI_TXSETPARAMSFLAGS_CS 0x0010 -#define FAPI_TXSETPARAMSFLAGS_SCAN_CHANNEL 0x0020 -#define FAPI_TXSETPARAMSFLAGS_SHORT_PREAMBLE 0x0040 -#define FAPI_TXSETPARAMSFLAGS_DISABLE_SCRAMBLER 0x0080 -#define FAPI_TXSETPARAMSFLAGS_LDPC 0x0100 -#define FAPI_TXSETPARAMSFLAGS_STBC 0x0200 -#define FAPI_TXSETPARAMSFLAGS_DISABLE_SPREADER 0x0400 -#define FAPI_TXSETPARAMSFLAGS_GREENFIELD_PREAMBLE 0x0800 -#define FAPI_TXSETPARAMSFLAGS_RX_LOW_POWER 0x1000 -#define FAPI_TXSETPARAMSFLAGS_IBSS_FRAMES 0x2000 -#define FAPI_TXSETPARAMSFLAGS_BEAMFORMING 0x4000 -#define FAPI_TXSETPARAMSFLAGS_DISABLE_EXTERNAL_LNA 0x8000 - -#define FAPI_TYPEOFAIRPOWER_EIRP 0x00 -#define FAPI_TYPEOFAIRPOWER_TPO 0x01 -#define FAPI_TYPEOFAIRPOWER_RAW 0x02 - -#define FAPI_USAGE_NO_USE 0x0 -#define FAPI_USAGE_USE 0x1 - -#define FAPI_VIFRANGE_VIF_INDEX_MIN 0x0001 -#define FAPI_VIFRANGE_VIF_INDEX_MAX 0x000f - -#define FAPI_VIFTYPE_UNSYNCHRONISED 0x0000 -#define FAPI_VIFTYPE_STATION 0x0002 -#define FAPI_VIFTYPE_AP 0x0003 -#define FAPI_VIFTYPE_WLANLITE 0x0004 -#define FAPI_VIFTYPE_NAN 0x0005 -#define FAPI_VIFTYPE_DISCOVERY 0x0006 -#define FAPI_VIFTYPE_PRECONNECT 0x0007 -#define FAPI_VIFTYPE_MONITOR 0x0010 -#define FAPI_VIFTYPE_SCAN 0x0020 -#define FAPI_VIFTYPE_OFFCHANNEL 0x0021 -#define FAPI_VIFTYPE_RANGE 0x0022 - -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P0 0x0000 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P1 0x0001 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P2 0x0002 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P3 0x0003 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P4 0x0004 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P5 0x0005 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P6 0x0006 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_P7 0x0007 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_20MHZ_PRIMARYCHANNELPOSITION_NOT_APPLICABLE 0x0008 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P0 0x0100 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P1 0x0101 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P2 0x0102 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P3 0x0103 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P4 0x0104 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P5 0x0105 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P6 0x0106 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_P7 0x0107 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_40MHZ_PRIMARYCHANNELPOSITION_NOT_APPLICABLE 0x0108 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P0 0x0200 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P1 0x0201 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P2 0x0202 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P3 0x0203 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P4 0x0204 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P5 0x0205 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P6 0x0206 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_P7 0x0207 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_80MHZ_PRIMARYCHANNELPOSITION_NOT_APPLICABLE 0x0208 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P0 0x0300 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P1 0x0301 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P2 0x0302 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P3 0x0303 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P4 0x0304 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P5 0x0305 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P6 0x0306 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_P7 0x0307 -#define FAPI_CHANNELBANDWIDTH_BANDWIDTH_160MHZ_PRIMARYCHANNELPOSITION_NOT_APPLICABLE 0x0308 - -#define MA_UNITDATA_REQ 0x1000 -#define MA_SPARE_1_REQ 0x1002 -#define MA_SPARE_2_REQ 0x1003 -#define MA_SPARE_3_REQ 0x1004 -#define MA_SPARE_SIGNAL_1_REQ 0x1005 -#define MA_SPARE_SIGNAL_2_REQ 0x1006 -#define MA_SPARE_SIGNAL_3_REQ 0x1007 -#define MA_UNITDATA_CFM 0x1100 -#define MA_SPARE_1_CFM 0x1102 -#define MA_SPARE_2_CFM 0x1103 -#define MA_SPARE_3_CFM 0x1104 -#define MA_SPARE_SIGNAL_1_CFM 0x1105 -#define MA_SPARE_SIGNAL_2_CFM 0x1106 -#define MA_SPARE_SIGNAL_3_CFM 0x1107 -#define MA_SPARE_1_RES 0x1200 -#define MA_SPARE_2_RES 0x1201 -#define MA_SPARE_3_RES 0x1202 -#define MA_SPARE_SIGNAL_1_RES 0x1203 -#define MA_SPARE_SIGNAL_2_RES 0x1204 -#define MA_SPARE_SIGNAL_3_RES 0x1205 -#define MA_UNITDATA_IND 0x1300 -#define MA_BLOCKACK_IND 0x1301 -#define MA_SPARE_1_IND 0x1302 -#define MA_SPARE_2_IND 0x1303 -#define MA_SPARE_3_IND 0x1304 -#define MA_SPARE_SIGNAL_1_IND 0x1305 -#define MA_SPARE_SIGNAL_2_IND 0x1306 -#define MA_SPARE_SIGNAL_3_IND 0x1307 -#define MLME_GET_REQ 0x2001 -#define MLME_SET_REQ 0x2002 -#define MLME_POWERMGT_REQ 0x2003 -#define MLME_ADD_INFO_ELEMENTS_REQ 0x2004 -#define MLME_ADD_SCAN_REQ 0x2005 -#define MLME_DEL_SCAN_REQ 0x2006 -#define MLME_ADD_VIF_REQ 0x2007 -#define MLME_DEL_VIF_REQ 0x2008 -#define MLME_START_REQ 0x2009 -#define MLME_SET_CHANNEL_REQ 0x200a -#define MLME_CONNECT_REQ 0x200b -#define MLME_REASSOCIATE_REQ 0x200c -#define MLME_ROAM_REQ 0x200d -#define MLME_DISCONNECT_REQ 0x200e -#define MLME_REGISTER_ACTION_FRAME_REQ 0x200f -#define MLME_SEND_FRAME_REQ 0x2010 -#define MLME_RESET_DWELL_TIME_REQ 0x2011 -#define MLME_SET_TRAFFIC_PARAMETERS_REQ 0x2012 -#define MLME_DEL_TRAFFIC_PARAMETERS_REQ 0x2013 -#define MLME_SET_PACKET_FILTER_REQ 0x2014 -#define MLME_SET_IP_ADDRESS_REQ 0x2015 -#define MLME_SET_ACL_REQ 0x2016 -#define MLME_SETKEYS_REQ 0x2018 -#define MLME_GET_KEY_SEQUENCE_REQ 0x201a -#define MLME_SET_PMK_REQ 0x201c -#define MLME_SET_CACHED_CHANNELS_REQ 0x201f -#define MLME_SET_WHITELIST_SSID_REQ 0x2020 -#define MLME_TDLS_ACTION_REQ 0x2021 -#define MLME_CHANNEL_SWITCH_REQ 0x2022 -#define MLME_MONITOR_RSSI_REQ 0x2023 -#define MLME_START_LINK_STATISTICS_REQ 0x2024 -#define MLME_STOP_LINK_STATISTICS_REQ 0x2025 -#define MLME_SET_PNO_LIST_REQ 0x2027 -#define MLME_HOST_STATE_REQ 0x2028 -#define MLME_ADD_RANGE_REQ 0x2029 -#define MLME_DEL_RANGE_REQ 0x202a -#define MLME_SET_NOA_REQ 0x202b -#define MLME_SET_CTWINDOW_REQ 0x202c -#define MLME_NAN_START_REQ 0x202d -#define MLME_NAN_CONFIG_REQ 0x202e -#define MLME_NAN_PUBLISH_REQ 0x202f -#define MLME_NAN_SUBSCRIBE_REQ 0x2030 -#define MLME_NAN_FOLLOWUP_REQ 0x2031 -#define MLME_UNSET_CHANNEL_REQ 0x2032 -#define MLME_SET_COUNTRY_REQ 0x2033 -#define MLME_FORWARD_BEACON_REQ 0x2034 -#define MLME_NDP_REQUEST_REQ 0x2035 -#define MLME_NDP_RESPONSE_REQ 0x2036 -#define MLME_NDP_TERMINATE_REQ 0x2037 -#define MLME_SPARE_4_REQ 0x203a -#define MLME_SPARE_5_REQ 0x203b -#define MLME_SPARE_6_REQ 0x203c -#define MLME_INSTALL_APF_REQ 0x203d -#define MLME_READ_APF_REQ 0x203e -#define MLME_SET_NUM_ANTENNAS_REQ 0x203f -#define MLME_ARP_DETECT_REQ 0x2040 -#define MLME_SPARE_SIGNAL_1_REQ 0x2041 -#define MLME_SPARE_SIGNAL_2_REQ 0x2042 -#define MLME_SPARE_SIGNAL_3_REQ 0x2043 -#define MLME_GET_CFM 0x2101 -#define MLME_SET_CFM 0x2102 -#define MLME_POWERMGT_CFM 0x2103 -#define MLME_ADD_INFO_ELEMENTS_CFM 0x2104 -#define MLME_ADD_SCAN_CFM 0x2105 -#define MLME_DEL_SCAN_CFM 0x2106 -#define MLME_ADD_VIF_CFM 0x2107 -#define MLME_DEL_VIF_CFM 0x2108 -#define MLME_START_CFM 0x2109 -#define MLME_SET_CHANNEL_CFM 0x210a -#define MLME_CONNECT_CFM 0x210b -#define MLME_REASSOCIATE_CFM 0x210c -#define MLME_ROAM_CFM 0x210d -#define MLME_DISCONNECT_CFM 0x210e -#define MLME_REGISTER_ACTION_FRAME_CFM 0x210f -#define MLME_SEND_FRAME_CFM 0x2110 -#define MLME_RESET_DWELL_TIME_CFM 0x2111 -#define MLME_SET_TRAFFIC_PARAMETERS_CFM 0x2112 -#define MLME_DEL_TRAFFIC_PARAMETERS_CFM 0x2113 -#define MLME_SET_PACKET_FILTER_CFM 0x2114 -#define MLME_SET_IP_ADDRESS_CFM 0x2115 -#define MLME_SET_ACL_CFM 0x2116 -#define MLME_SETKEYS_CFM 0x2118 -#define MLME_GET_KEY_SEQUENCE_CFM 0x211a -#define MLME_SET_PMK_CFM 0x211c -#define MLME_SET_CACHED_CHANNELS_CFM 0x211f -#define MLME_SET_WHITELIST_SSID_CFM 0x2120 -#define MLME_TDLS_ACTION_CFM 0x2121 -#define MLME_CHANNEL_SWITCH_CFM 0x2122 -#define MLME_MONITOR_RSSI_CFM 0x2123 -#define MLME_START_LINK_STATISTICS_CFM 0x2124 -#define MLME_STOP_LINK_STATISTICS_CFM 0x2125 -#define MLME_SET_PNO_LIST_CFM 0x2127 -#define MLME_HOST_STATE_CFM 0x2128 -#define MLME_ADD_RANGE_CFM 0x2129 -#define MLME_DEL_RANGE_CFM 0x212a -#define MLME_SET_NOA_CFM 0x212b -#define MLME_SET_CTWINDOW_CFM 0x212c -#define MLME_NAN_START_CFM 0x212d -#define MLME_NAN_CONFIG_CFM 0x212e -#define MLME_NAN_PUBLISH_CFM 0x212f -#define MLME_NAN_SUBSCRIBE_CFM 0x2130 -#define MLME_NAN_FOLLOWUP_CFM 0x2131 -#define MLME_UNSET_CHANNEL_CFM 0x2132 -#define MLME_SET_COUNTRY_CFM 0x2133 -#define MLME_FORWARD_BEACON_CFM 0x2134 -#define MLME_NDP_REQUEST_CFM 0x2135 -#define MLME_NDP_RESPONSE_CFM 0x2136 -#define MLME_NDP_TERMINATE_CFM 0x2137 -#define MLME_SPARE_4_CFM 0x213a -#define MLME_SPARE_5_CFM 0x213b -#define MLME_SPARE_6_CFM 0x213c -#define MLME_INSTALL_APF_CFM 0x213d -#define MLME_READ_APF_CFM 0x213e -#define MLME_SET_NUM_ANTENNAS_CFM 0x213f -#define MLME_ARP_DETECT_CFM 0x2140 -#define MLME_SPARE_SIGNAL_1_CFM 0x2141 -#define MLME_SPARE_SIGNAL_2_CFM 0x2142 -#define MLME_SPARE_SIGNAL_3_CFM 0x2143 -#define MLME_CONNECT_RES 0x2200 -#define MLME_CONNECTED_RES 0x2201 -#define MLME_REASSOCIATE_RES 0x2202 -#define MLME_ROAMED_RES 0x2203 -#define MLME_TDLS_PEER_RES 0x2204 -#define MLME_SYNCHRONISED_RES 0x2205 -#define MLME_SPARE_2_RES 0x2206 -#define MLME_SPARE_3_RES 0x2207 -#define MLME_SPARE_4_RES 0x2208 -#define MLME_SPARE_SIGNAL_1_RES 0x2209 -#define MLME_SPARE_SIGNAL_2_RES 0x220a -#define MLME_SPARE_SIGNAL_3_RES 0x220b -#define MLME_SCAN_IND 0x2300 -#define MLME_SCAN_DONE_IND 0x2301 -#define MLME_LISTEN_END_IND 0x2302 -#define MLME_CONNECT_IND 0x2303 -#define MLME_CONNECTED_IND 0x2304 -#define MLME_REASSOCIATE_IND 0x2305 -#define MLME_ROAM_IND 0x2306 -#define MLME_ROAMED_IND 0x2307 -#define MLME_DISCONNECT_IND 0x2308 -#define MLME_DISCONNECTED_IND 0x2309 -#define MLME_PROCEDURE_STARTED_IND 0x230a -#define MLME_MIC_FAILURE_IND 0x230b -#define MLME_FRAME_TRANSMISSION_IND 0x230c -#define MLME_RECEIVED_FRAME_IND 0x230d -#define MLME_TDLS_PEER_IND 0x230f -#define MLME_RSSI_REPORT_IND 0x2312 -#define MLME_AC_PRIORITY_UPDATE_IND 0x2313 -#define MLME_RANGE_IND 0x2314 -#define MLME_RANGE_DONE_IND 0x2315 -#define MLME_EVENT_LOG_IND 0x2316 -#define MLME_NAN_EVENT_IND 0x2317 -#define MLME_NAN_SERVICE_IND 0x2318 -#define MLME_NAN_FOLLOWUP_IND 0x2319 -#define MLME_CHANNEL_SWITCHED_IND 0x231a -#define MLME_SYNCHRONISED_IND 0x231b -#define MLME_BEACON_REPORTING_EVENT_IND 0x231c -#define MLME_SPARE_3_IND 0x231d -#define MLME_SPARE_4_IND 0x231e -#define MLME_NDP_REQUEST_IND 0x231f -#define MLME_NDP_REQUESTED_IND 0x2320 -#define MLME_NDP_RESPONSE_IND 0x2321 -#define MLME_NDP_TERMINATE_IND 0x2322 -#define MLME_NDP_TERMINATED_IND 0x2323 -#define MLME_SPARE_5_IND 0x2324 -#define MLME_SPARE_SIGNAL_1_IND 0x2325 -#define MLME_SPARE_SIGNAL_2_IND 0x2326 -#define MLME_SPARE_SIGNAL_3_IND 0x2327 -#define DEBUG_SPARE_1_REQ 0x8000 -#define DEBUG_SPARE_2_REQ 0x8001 -#define DEBUG_SPARE_3_REQ 0x8002 -#define DEBUG_SPARE_SIGNAL_1_REQ 0x8003 -#define DEBUG_SPARE_SIGNAL_2_REQ 0x8004 -#define DEBUG_SPARE_SIGNAL_3_REQ 0x8005 -#define DEBUG_SPARE_1_CFM 0x8100 -#define DEBUG_SPARE_2_CFM 0x8101 -#define DEBUG_SPARE_3_CFM 0x8102 -#define DEBUG_SPARE_SIGNAL_1_CFM 0x8103 -#define DEBUG_SPARE_SIGNAL_2_CFM 0x8104 -#define DEBUG_SPARE_SIGNAL_3_CFM 0x8105 -#define DEBUG_SPARE_1_RES 0x8200 -#define DEBUG_SPARE_2_RES 0x8201 -#define DEBUG_SPARE_3_RES 0x8202 -#define DEBUG_SPARE_SIGNAL_1_RES 0x8203 -#define DEBUG_SPARE_SIGNAL_2_RES 0x8204 -#define DEBUG_SPARE_SIGNAL_3_RES 0x8205 -#define DEBUG_WORD12IND 0x8301 -#define DEBUG_FAULT_IND 0x8302 -#define DEBUG_WORDS_IND 0x8303 -#define DEBUG_SPARE_2_IND 0x8304 -#define DEBUG_SPARE_3_IND 0x8305 -#define DEBUG_SPARE_4_IND 0x8306 -#define DEBUG_SPARE_SIGNAL_1_IND 0x8307 -#define DEBUG_SPARE_SIGNAL_2_IND 0x8308 -#define DEBUG_SPARE_SIGNAL_3_IND 0x8309 -#define TEST_BLOCK_REQUESTS_REQ 0x9000 -#define TEST_PANIC_REQ 0x9001 -#define TEST_SUSPEND_REQ 0x9002 -#define TEST_RESUME_REQ 0x9003 -#define RADIO_LOGGING_REQ 0x9004 -#define WLANLITE_CW_START_REQ 0x9005 -#define WLANLITE_CW_STOP_REQ 0x9006 -#define WLANLITE_TX_SET_PARAMS_REQ 0x9007 -#define WLANLITE_TX_START_REQ 0x9008 -#define WLANLITE_TX_READ_REQ 0x9009 -#define WLANLITE_TX_STOP_REQ 0x900a -#define WLANLITE_RX_START_REQ 0x900b -#define WLANLITE_RX_READ_REQ 0x900c -#define WLANLITE_RX_STOP_REQ 0x900d -#define WLANLITE_STATUS_REQ 0x900e -#define TEST_PMALLOC_REQ 0x900f -#define TEST_CONFIGURE_MONITOR_MODE_REQ 0x9010 -#define TEST_CHECK_FW_ALIVE_REQ 0x9012 -#define DEBUG_GENERIC_REQ 0x9013 -#define DEBUG_PKT_SINK_START_REQ 0x9014 -#define DEBUG_PKT_SINK_STOP_REQ 0x9015 -#define DEBUG_PKT_SINK_REPORT_REQ 0x9016 -#define DEBUG_PKT_GEN_START_REQ 0x9017 -#define DEBUG_PKT_GEN_STOP_REQ 0x9018 -#define DEBUG_PKT_GEN_REPORT_REQ 0x9019 -#define WLANLITE_RADIO_SELECT_REQ 0x901a -#define TEST_HIP_TESTER_START_REQ 0x901b -#define TEST_HIP_TESTER_STOP_REQ 0x901c -#define TEST_HIP_TESTER_SET_PARAMS_REQ 0x901d -#define TEST_HIP_TESTER_REPORT_REQ 0x901e -#define TEST_BIST_GET_TX_GAIN_REQ 0x901f -#define TEST_SPARE_1_REQ 0x9020 -#define TEST_SPARE_2_REQ 0x9021 -#define TEST_SPARE_3_REQ 0x9022 -#define TEST_SPARE_SIGNAL_1_REQ 0x9023 -#define TEST_SPARE_SIGNAL_2_REQ 0x9024 -#define TEST_SPARE_SIGNAL_3_REQ 0x9025 -#define RADIO_LOGGING_CFM 0x9100 -#define WLANLITE_CW_START_CFM 0x9101 -#define WLANLITE_TX_SET_PARAMS_CFM 0x9102 -#define WLANLITE_CW_STOP_CFM 0x9103 -#define WLANLITE_TX_START_CFM 0x9104 -#define WLANLITE_TX_READ_CFM 0x9105 -#define WLANLITE_TX_STOP_CFM 0x9106 -#define WLANLITE_RX_START_CFM 0x9107 -#define WLANLITE_RX_READ_CFM 0x9108 -#define WLANLITE_RX_STOP_CFM 0x9109 -#define WLANLITE_STATUS_CFM 0x910a -#define TEST_PMALLOC_CFM 0x910b -#define TEST_CONFIGURE_MONITOR_MODE_CFM 0x910c -#define TEST_CHECK_FW_ALIVE_CFM 0x910e -#define TEST_SUSPEND_CFM 0x910f -#define TEST_RESUME_CFM 0x9110 -#define DEBUG_GENERIC_CFM 0x9111 -#define WLANLITE_RADIO_SELECT_CFM 0x9112 -#define TEST_HIP_TESTER_START_CFM 0x9113 -#define TEST_HIP_TESTER_STOP_CFM 0x9114 -#define TEST_HIP_TESTER_SET_PARAMS_CFM 0x9115 -#define TEST_BIST_GET_TX_GAIN_CFM 0x9116 -#define TEST_SPARE_1_CFM 0x9117 -#define TEST_SPARE_2_CFM 0x9118 -#define TEST_SPARE_3_CFM 0x9119 -#define TEST_SPARE_SIGNAL_1_CFM 0x911a -#define TEST_SPARE_SIGNAL_2_CFM 0x911b -#define TEST_SPARE_SIGNAL_3_CFM 0x911c -#define TEST_SPARE_1_RES 0x9200 -#define TEST_SPARE_2_RES 0x9201 -#define TEST_SPARE_3_RES 0x9202 -#define TEST_SPARE_SIGNAL_1_RES 0x9203 -#define TEST_SPARE_SIGNAL_2_RES 0x9204 -#define TEST_SPARE_SIGNAL_3_RES 0x9205 -#define RADIO_LOGGING_IND 0x9300 -#define DEBUG_GENERIC_IND 0x9301 -#define DEBUG_PKT_SINK_REPORT_IND 0x9302 -#define DEBUG_PKT_GEN_REPORT_IND 0x9303 -#define TEST_HIP_TESTER_REPORT_IND 0x9304 -#define TEST_SPARE_1_IND 0x9305 -#define TEST_SPARE_2_IND 0x9306 -#define TEST_SPARE_3_IND 0x9307 -#define TEST_SPARE_SIGNAL_1_IND 0x9308 -#define TEST_SPARE_SIGNAL_2_IND 0x9309 -#define TEST_SPARE_SIGNAL_3_IND 0x930a - -struct fapi_signal_header { - __le16 id; - __le16 receiver_pid; - __le16 sender_pid; - __le32 fw_reference; -} __packed; - -struct fapi_vif_signal_header { - __le16 id; - __le16 receiver_pid; - __le16 sender_pid; - __le32 fw_reference; - __le16 vif; -} __packed; - -struct fapi_signal { - __le16 id; - __le16 receiver_pid; - __le16 sender_pid; - __le32 fw_reference; - - union { - struct { - __le16 vif; - __le16 host_tag; - __le16 priority; - __le16 peer_index; - __le16 data_unit_descriptor; - __le16 bulk_data_descriptor; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_unitdata_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_1_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_2_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_3_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_1_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_2_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_3_req; - struct { - __le16 vif; - __le16 transmission_status; - __le16 host_tag; - __le16 sequence_number; - __le16 peer_index; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_unitdata_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_1_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_2_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_3_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_1_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_2_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_3_cfm; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_1_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_3_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_1_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_3_res; - struct { - __le16 vif; - __le16 data_unit_descriptor; - __le16 sequence_number; - __le16 priority; - __le16 peer_index; - __le16 proprieraty_information_length; - __le16 bulk_data_descriptor; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_unitdata_ind; - struct { - __le16 vif; - u8 peer_qsta_address[ETH_ALEN]; - __le16 sequence_number; - __le16 reason_code; - __le16 blockack_parameter_set; - __le16 direction; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_blockack_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_1_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_2_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_3_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_1_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_2_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed ma_spare_signal_3_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_get_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_req; - struct { - __le16 vif; - __le16 power_management_mode; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_powermgt_req; - struct { - __le16 vif; - __le16 purpose; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_info_elements_req; - struct { - __le16 vif; - __le16 scan_id; - __le16 scan_type; - u8 device_address[ETH_ALEN]; - __le16 report_mode_bitmap; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_scan_req; - struct { - __le16 vif; - __le16 scan_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_scan_req; - struct { - __le16 vif; - u8 interface_address[ETH_ALEN]; - __le16 virtual_interface_type; - u8 device_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_vif_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_vif_req; - struct { - __le16 vif; - u8 bssid[ETH_ALEN]; - __le16 beacon_period; - __le16 dtim_period; - __le16 capability_information; - __le16 authentication_type; - __le16 hidden_ssid; - __le16 channel_frequency; - __le16 channel_information; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_start_req; - struct { - __le16 vif; - __le16 availability_duration; - __le16 availability_interval; - __le16 count; - __le16 channel_frequency; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_channel_req; - struct { - __le16 vif; - u8 bssid[ETH_ALEN]; - __le16 authentication_type; - __le16 channel_frequency; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_connect_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_reassociate_req; - struct { - __le16 vif; - u8 bssid[ETH_ALEN]; - __le16 channel_frequency; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_roam_req; - struct { - __le16 vif; - u8 peer_sta_address[ETH_ALEN]; - __le16 reason_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_disconnect_req; - struct { - __le16 vif; - __le32 action_frame_category_bitmap_active; - __le32 action_frame_category_bitmap_suspended; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_register_action_frame_req; - struct { - __le16 vif; - __le16 host_tag; - __le16 data_unit_descriptor; - __le16 message_type; - __le16 channel_frequency; - __le32 dwell_time; - __le32 period; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_send_frame_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_reset_dwell_time_req; - struct { - __le16 vif; - __le16 user_priority; - __le16 medium_time; - __le16 minimum_data_rate; - u8 peer_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_traffic_parameters_req; - struct { - __le16 vif; - __le16 user_priority; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_traffic_parameters_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_packet_filter_req; - struct { - __le16 vif; - __le16 ip_version; - u8 multicast_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_ip_address_req; - struct { - __le16 vif; - __le16 entries; - __le16 acl_policy; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_acl_req; - struct { - __le16 vif; - __le16 length; - __le16 key_id; - __le16 key_type; - u8 address[ETH_ALEN]; - __le16 sequence_number[8]; - __le32 cipher_suite_selector; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_setkeys_req; - struct { - __le16 vif; - __le16 key_id; - __le16 key_type; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_get_key_sequence_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_pmk_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_cached_channels_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_whitelist_ssid_req; - struct { - __le16 vif; - u8 peer_sta_address[ETH_ALEN]; - __le16 tdls_action; - __le16 channel_frequency; - __le16 channel_information; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_tdls_action_req; - struct { - __le16 vif; - __le16 channel_frequency; - __le16 channel_information; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_channel_switch_req; - struct { - __le16 vif; - __le16 low_rssi_threshold; - __le16 high_rssi_threshold; - __le16 rssi_monitoring_enabled; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_monitor_rssi_req; - struct { - __le16 vif; - __le16 mpdu_size_threshold; - __le16 aggressive_statistics_gathering_enabled; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_start_link_statistics_req; - struct { - __le16 vif; - __le16 statistics_stop_bitmap; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_stop_link_statistics_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_pno_list_req; - struct { - __le16 vif; - __le16 host_state; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_host_state_req; - struct { - __le16 vif; - __le16 rtt_id; - u8 device_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_range_req; - struct { - __le16 vif; - __le16 rtt_id; - __le16 entries; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_range_req; - struct { - __le16 vif; - __le16 request_id; - __le16 noa_count; - __le32 interval; - __le32 duration; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_noa_req; - struct { - __le16 vif; - __le16 ctwindow; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_ctwindow_req; - struct { - __le16 vif; - __le16 nan_operation_control_flags; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_start_req; - struct { - __le16 vif; - __le16 nan_operation_control_flags; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_config_req; - struct { - __le16 vif; - __le16 publish_id; - __le16 nan_sdf_flags; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_publish_req; - struct { - __le16 vif; - __le16 subscribe_id; - __le16 nan_sdf_flags; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_subscribe_req; - struct { - __le16 vif; - __le16 publish_subscribe_id; - __le16 match_id; - __le16 nan_sdf_flags; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_followup_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_unset_channel_req; - struct { - __le16 vif; - __le16 country_code; - __le16 dfs_regulatory_domain; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_country_req; - struct { - __le16 vif; - __le16 wips_action; - __le16 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_forward_beacon_req; - struct { - __le16 vif; - __le16 ndl_vif_index; - __le16 match_id; - u8 local_ndp_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_request_req; - struct { - __le16 vif; - __le16 local_ndp_id; - __le16 ndl_vif_index; - __le16 reason_code; - u8 local_ndp_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_response_req; - struct { - __le16 vif; - __le16 ndl_vif_index; - u8 local_ndp_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_terminate_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_4_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_5_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_6_req; - struct { - __le16 vif; - __le16 filter_mode; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_install_apf_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_read_apf_req; - struct { - __le16 vif; - __le16 number_of_antennas; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_num_antennas_req; - struct { - __le16 vif; - __le16 arp_detect_action; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_arp_detect_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_1_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_2_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_3_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_get_cfm; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_powermgt_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_info_elements_cfm; - struct { - __le16 vif; - __le16 result_code; - __le16 scan_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_scan_cfm; - struct { - __le16 vif; - __le16 result_code; - __le16 scan_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_scan_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_vif_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_vif_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_start_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_channel_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_connect_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_reassociate_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_roam_cfm; - struct { - __le16 vif; - u8 peer_sta_address[ETH_ALEN]; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_disconnect_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_register_action_frame_cfm; - struct { - __le16 vif; - __le16 host_tag; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_send_frame_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_reset_dwell_time_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_traffic_parameters_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_traffic_parameters_cfm; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_packet_filter_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_ip_address_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_acl_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_setkeys_cfm; - struct { - __le16 vif; - __le16 sequence_number[8]; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_get_key_sequence_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_pmk_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_cached_channels_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_whitelist_ssid_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_tdls_action_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_channel_switch_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_monitor_rssi_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_start_link_statistics_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_stop_link_statistics_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_pno_list_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_host_state_cfm; - struct { - __le16 vif; - __le16 result_code; - __le16 rtt_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_add_range_cfm; - struct { - __le16 vif; - __le16 result_code; - __le16 rtt_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_del_range_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_noa_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_ctwindow_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_start_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_config_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_publish_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_subscribe_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_followup_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_unset_channel_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_country_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_forward_beacon_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_request_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_response_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_terminate_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_4_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_5_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_6_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_install_apf_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_read_apf_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_set_num_antennas_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_arp_detect_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_1_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_2_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_3_cfm; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_connect_res; - struct { - __le16 vif; - __le16 association_identifier; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_connected_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_reassociate_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_roamed_res; - struct { - __le16 vif; - __le16 peer_index; - __le16 tdls_event; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_tdls_peer_res; - struct { - __le16 vif; - __le16 result_code; - u8 bssid[ETH_ALEN]; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_synchronised_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_3_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_4_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_1_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_3_res; - struct { - __le16 vif; - __le16 channel_frequency; - __le16 rssi; - __le16 scan_id; - __le16 hotlisted_ap; - __le16 preferrednetwork_ap; - __le16 anqp_elements_length; - __le16 network_block_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_scan_ind; - struct { - __le16 vif; - __le16 scan_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_scan_done_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_listen_end_ind; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_connect_ind; - struct { - __le16 vif; - __le16 association_identifier; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_connected_ind; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_reassociate_ind; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_roam_ind; - struct { - __le16 vif; - __le16 temporal_keys_required; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_roamed_ind; - struct { - __le16 vif; - u8 peer_sta_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_disconnect_ind; - struct { - __le16 vif; - u8 peer_sta_address[ETH_ALEN]; - __le16 reason_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_disconnected_ind; - struct { - __le16 vif; - __le16 procedure_type; - __le16 association_identifier; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_procedure_started_ind; - struct { - __le16 vif; - u8 peer_sta_address[ETH_ALEN]; - __le16 key_type; - __le16 key_id; - __le16 key_sequence_number[8]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_mic_failure_ind; - struct { - __le16 vif; - __le16 host_tag; - __le16 transmission_status; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_frame_transmission_ind; - struct { - __le16 vif; - __le16 data_unit_descriptor; - __le16 channel_frequency; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_received_frame_ind; - struct { - __le16 vif; - u8 peer_sta_address[ETH_ALEN]; - __le16 peer_index; - __le16 tdls_event; - __le16 reason_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_tdls_peer_ind; - struct { - __le16 vif; - u8 bssid[ETH_ALEN]; - __le16 rssi; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_rssi_report_ind; - struct { - __le16 vif; - __le16 ac_priority; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ac_priority_update_ind; - struct { - __le16 vif; - __le16 rtt_id; - __le16 entries; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_range_ind; - struct { - __le16 vif; - __le16 rtt_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_range_done_ind; - struct { - __le16 vif; - __le16 event; - u8 timestamp[8]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_event_log_ind; - struct { - __le16 vif; - __le16 event; - __le16 identifier; - u8 address_or_identifier[ETH_ALEN]; - __le16 reason_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_event_ind; - struct { - __le16 vif; - __le16 publish_subscribe_id; - __le16 match_id; - __le32 ranging_measurement; - __le16 rangingindicationtype; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_service_ind; - struct { - __le16 vif; - __le16 publish_subscribe_id; - __le16 match_id; - u8 peer_nan_management_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_nan_followup_ind; - struct { - __le16 vif; - __le16 channel_frequency; - __le16 channel_information; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_channel_switched_ind; - struct { - __le16 vif; - __le16 rssi; - __le16 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_synchronised_ind; - struct { - __le16 vif; - __le16 abort_reason; - __le16 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_beacon_reporting_event_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_3_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_4_ind; - struct { - __le16 vif; - __le16 ndl_vif_index; - u8 peer_ndp_interface_address[ETH_ALEN]; - __le16 result_code; - u8 local_ndp_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_request_ind; - struct { - __le16 vif; - __le16 publish_subscribe_id; - __le16 local_ndp_id; - u8 peer_nan_management_interface_address[ETH_ALEN]; - __le16 security_required; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_requested_ind; - struct { - __le16 vif; - __le16 ndl_vif_index; - u8 peer_ndp_interface_address[ETH_ALEN]; - __le16 result_code; - u8 local_ndp_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_response_ind; - struct { - __le16 vif; - __le16 ndl_vif_index; - u8 local_ndp_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_terminate_ind; - struct { - __le16 vif; - __le16 ndl_vif_index; - u8 local_ndp_interface_address[ETH_ALEN]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_ndp_terminated_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_5_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_1_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_2_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed mlme_spare_signal_3_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_1_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_2_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_3_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_1_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_2_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_3_req; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_1_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_2_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_3_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_1_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_2_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_3_cfm; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_1_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_3_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_1_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_3_res; - struct { - __le16 vif; - __le16 module_id; - __le16 module_sub_id; - __le32 timestamp; - __le16 debug_words[12]; - __le16 sequence_number; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_word12_ind; - struct { - __le16 vif; - __le16 faultid; - __le16 count; - __le32 timestamp; - __le32 arg; - __le16 cpu; - __le16 sequence_number; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_fault_ind; - struct { - __le16 vif; - __le16 module_id; - __le16 module_sub_id; - __le32 timestamp; - __le16 sequence_number; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_words_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_2_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_3_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_4_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_1_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_2_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_spare_signal_3_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_block_requests_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_panic_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_suspend_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_resume_req; - struct { - __le32 logging_source; - __le32 logging_frequency; - __le32 capture_stream; - __le32 trigger_mode; - __le32 delay; - __le32 buffer_size; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed radio_logging_req; - struct { - __le16 freq; - __le16 power; - __le16 flags; - __le16 type; - __le16 amplitude; - __le32 freq1; - __le32 freq2; - __le16 phase; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_cw_start_req; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_cw_stop_req; - struct { - __le16 freq; - __le16 rate; - __le16 channel_information; - __le16 power; - __le16 length; - __le32 interval; - __le16 flags; - __le16 aid; - __le16 distance_to_band_edge_half_mhz; - __le16 regulatory_domain; - __le16 spare_0; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_set_params_req; - struct { - __le32 num_frames_to_send; - __le16 data_type; - __le16 data_param; - u8 dest_addr[ETH_ALEN]; - u8 src_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - __le16 num_mpdus_per_ampdu; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_start_req; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_read_req; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_stop_req; - struct { - __le16 freq; - __le16 channel_information; - __le16 flags; - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - __le16 aid; - __le16 num_mpdus_per_ampdu; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_rx_start_req; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_rx_read_req; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_rx_stop_req; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_status_req; - struct { - __le16 alloc_area; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_pmalloc_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_configure_monitor_mode_req; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_check_fw_alive_req; - struct { - __le16 vif; - __le16 debug_words[8]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_generic_req; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 interval; - __le16 packets_per_interval; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_sink_start_req; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_sink_stop_req; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 report_interval; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_sink_report_req; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 interval; - __le16 size; - __le16 packets_per_interval; - __le32 ipv4destination_address; - __le16 packets_per_interrupt; - __le16 use_streaming; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_gen_start_req; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_gen_stop_req; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 report_interval; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_gen_report_req; - struct { - __le16 radio_bitmap; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_radio_select_req; - struct { - __le16 vif; - __le16 mode; - __le16 end_point; - __le16 protocol; - __le32 interval; - __le16 packets_per_interval; - __le16 packets_size; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_start_req; - struct { - __le16 vif; - __le16 stream_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_stop_req; - struct { - __le16 vif; - __le16 stream_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_set_params_req; - struct { - __le16 vif; - __le16 stream_id; - __le32 report_interval; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_report_req; - struct { - __le16 freq; - __le16 tx_gain; - __le16 rx_gain; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_bist_get_tx_gain_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_1_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_2_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_3_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_1_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_2_req; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_3_req; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed radio_logging_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_cw_start_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_set_params_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_cw_stop_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_start_cfm; - struct { - __le16 result_code; - __le16 flags; - __le32 ctr_frames_left_to_send; - __le32 transmission_back_off; - __le16 wanted_power_target; - __le16 final_power_target; - __le16 oob_constraint; - __le16 last_trim_pa_temperature; - __le16 current_pa_temperature; - __le16 last_trim_ambient_temperature; - __le16 current_ambient_temperature; - __le16 temp_power_adjust; - __le32 ctr_frames_success; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_read_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_tx_stop_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_rx_start_cfm; - struct { - __le16 result_code; - __le32 freq_offset_cur; - __le32 freq_offset_avg; - __le16 rssi_cur; - __le16 rssi_avg; - __le16 rssi_min; - __le16 rssi_max; - __le16 snr_cur; - __le16 snr_avg; - __le16 snr_min; - __le16 snr_max; - __le32 interval; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_rx_read_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_rx_stop_cfm; - struct { - __le16 result_code; - __le16 device_state; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_status_cfm; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_pmalloc_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_configure_monitor_mode_cfm; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_check_fw_alive_cfm; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_suspend_cfm; - struct { - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_resume_cfm; - struct { - __le16 vif; - __le16 debug_words[8]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_generic_cfm; - struct { - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed wlanlite_radio_select_cfm; - struct { - __le16 vif; - __le16 result_code; - __le16 stream_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_start_cfm; - struct { - __le16 vif; - __le16 result_code; - __le16 stream_id; - __le32 duration; - __le32 count; - __le32 failed_count; - __le32 octets; - __le32 mbps; - __le16 idle_ratio; - __le16 int_latency; - __le32 tester_reserved1; - __le32 tester_reserved2; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_stop_cfm; - struct { - __le16 vif; - __le16 result_code; - __le16 stream_id; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_set_params_cfm; - struct { - __le16 result_code; - __le32 gain; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_bist_get_tx_gain_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_1_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_2_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_3_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_1_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_2_cfm; - struct { - __le16 vif; - __le16 result_code; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_3_cfm; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_1_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_3_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_1_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_2_res; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_3_res; - struct { - __le32 sequence_number; - __le32 more_data; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed radio_logging_ind; - struct { - __le16 vif; - __le16 debug_words[8]; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_generic_ind; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 duration; - __le32 received_packets; - __le32 received_octets; - __le32 kbps; - __le16 idle_ratio; - __le16 int_latency; - __le16 free_kbytes; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_sink_report_ind; - struct { - __le16 vif; - __le16 end_point; - __le16 direction; - __le32 duration; - __le32 received_packets; - __le32 failed_count; - __le32 received_octets; - __le32 kbps; - __le16 idle_ratio; - __le16 int_latency; - __le16 free_kbytes; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed debug_pkt_gen_report_ind; - struct { - __le16 vif; - __le16 stream_id; - __le32 duration; - __le32 count; - __le32 failed_count; - __le32 octets; - __le32 mbps; - __le16 idle_ratio; - __le16 int_latency; - __le32 tester_reserved1; - __le32 tester_reserved2; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_hip_tester_report_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_1_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_2_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_3_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_1_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_2_ind; - struct { - __le16 vif; - __le32 spare_1; - __le32 spare_2; - __le32 spare_3; - u8 dr[0]; - } __packed test_spare_signal_3_ind; - } u; -} __packed; - -static inline struct sk_buff *fapi_alloc_f(size_t sig_size, size_t data_size, u16 id, u16 vif, const char *file, int line) -{ - struct sk_buff *skb = slsi_alloc_skb_f(sig_size + data_size, GFP_ATOMIC, file, line); - struct fapi_vif_signal_header *header; - - WARN_ON(sig_size < sizeof(struct fapi_signal_header)); - if (WARN_ON(!skb)) - return NULL; - - slsi_skb_cb_init(skb)->sig_length = sig_size; - slsi_skb_cb_get(skb)->data_length = sig_size; - - header = (struct fapi_vif_signal_header *)skb_put(skb, sig_size); - header->id = cpu_to_le16(id); - header->receiver_pid = 0; - header->sender_pid = 0; - header->fw_reference = 0; - header->vif = vif; - return skb; -} - -#define fapi_sig_size(mp_name) ((u16)offsetof(struct fapi_signal, u.mp_name.dr)) -#define fapi_alloc(mp_name, mp_id, mp_vif, mp_datalen) fapi_alloc_f(fapi_sig_size(mp_name), mp_datalen, mp_id, mp_vif, __FILE__, __LINE__) -#define fapi_get_buff(mp_skb, mp_name) (((struct fapi_signal *)(mp_skb)->data)->mp_name) -#define fapi_get_u16(mp_skb, mp_name) le16_to_cpu(((struct fapi_signal *)(mp_skb)->data)->mp_name) -#define fapi_get_u32(mp_skb, mp_name) le32_to_cpu(((struct fapi_signal *)(mp_skb)->data)->mp_name) -#define fapi_get_u64(mp_skb, mp_name) le64_to_cpu(((struct fapi_signal *)(mp_skb)->data)->mp_name) -#define fapi_set_u16(mp_skb, mp_name, mp_value) (((struct fapi_signal *)(mp_skb)->data)->mp_name = cpu_to_le16(mp_value)) -#define fapi_set_u32(mp_skb, mp_name, mp_value) (((struct fapi_signal *)(mp_skb)->data)->mp_name = cpu_to_le32(mp_value)) -#define fapi_get_s16(mp_skb, mp_name) ((s16)le16_to_cpu(((struct fapi_signal *)(mp_skb)->data)->mp_name)) -#define fapi_get_s32(mp_skb, mp_name) ((s32)le32_to_cpu(((struct fapi_signal *)(mp_skb)->data)->mp_name)) -#define fapi_set_s16(mp_skb, mp_name, mp_value) (((struct fapi_signal *)(mp_skb)->data)->mp_name = cpu_to_le16((u16)mp_value)) -#define fapi_set_s32(mp_skb, mp_name, mp_value) (((struct fapi_signal *)(mp_skb)->data)->mp_name = cpu_to_le32((u32)mp_value)) -#define fapi_set_memcpy(mp_skb, mp_name, mp_value) memcpy(((struct fapi_signal *)(mp_skb)->data)->mp_name, mp_value, sizeof(((struct fapi_signal *)(mp_skb)->data)->mp_name)) -#define fapi_set_memset(mp_skb, mp_name, mp_value) memset(((struct fapi_signal *)(mp_skb)->data)->mp_name, mp_value, sizeof(((struct fapi_signal *)(mp_skb)->data)->mp_name)) - -/* Helper to get and set high/low 16 bits from u32 signals */ -#define fapi_get_high16_u32(mp_skb, mp_name) ((fapi_get_u32((mp_skb), mp_name) & 0xffff0000) >> 16) -#define fapi_set_high16_u32(mp_skb, mp_name, mp_value) fapi_set_u32((mp_skb), mp_name, (fapi_get_u32((mp_skb), mp_name) & 0xffff) | ((mp_value) << 16)) -#define fapi_get_low16_u32(mp_skb, mp_name) (fapi_get_u32((mp_skb), mp_name) & 0xffff) -#define fapi_set_low16_u32(mp_skb, mp_name, mp_value) fapi_set_u32((mp_skb), mp_name, (fapi_get_u32((mp_skb), mp_name) & 0xffff0000) | (mp_value)) - -/* Helper to get signal and data */ -#define fapi_get_sigid(mp_skb) le16_to_cpu(((struct fapi_signal *)(mp_skb)->data)->id) -#define fapi_get_siglen(mp_skb) (slsi_skb_cb_get(mp_skb)->sig_length) -#define fapi_get_datalen(mp_skb) (slsi_skb_cb_get(mp_skb)->data_length - slsi_skb_cb_get(mp_skb)->sig_length) -#define fapi_get_data(mp_skb) (mp_skb->data + fapi_get_siglen(mp_skb)) -#define fapi_get_vif(mp_skb) le16_to_cpu(((struct fapi_vif_signal_header *)(mp_skb)->data)->vif) - -/* Helper to get the struct ieee80211_mgmt from the data */ -#define fapi_get_mgmt(mp_skb) ((struct ieee80211_mgmt *)fapi_get_data(mp_skb)) -#define fapi_get_mgmtlen(mp_skb) fapi_get_datalen(mp_skb) - -static inline u8 *fapi_append_data(struct sk_buff *skb, const u8 *data, size_t data_len) -{ - u8 *p; - - if (WARN_ON(skb_tailroom(skb) < data_len)) - return NULL; - - p = skb_put(skb, data_len); - slsi_skb_cb_get(skb)->data_length += data_len; - if (data) - memcpy(p, data, data_len); - return p; -} - -static inline u8 *fapi_append_data_u32(struct sk_buff *skb, const u32 data) -{ - __le32 val = cpu_to_le32(data); - - return fapi_append_data(skb, (u8 *)&val, sizeof(val)); -} - -static inline u8 *fapi_append_data_u16(struct sk_buff *skb, const u16 data) -{ - __le16 val = cpu_to_le16(data); - - return fapi_append_data(skb, (u8 *)&val, sizeof(val)); -} - -static inline u8 *fapi_append_data_u8(struct sk_buff *skb, const u8 data) -{ - u8 val = data; - - return fapi_append_data(skb, (u8 *)&val, sizeof(val)); -} - -#define fapi_append_data_bool(skb, data) fapi_append_data_u16(skb, data) - -static inline bool fapi_is_mlme(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SAP_TYPE_MASK) == FAPI_SAP_TYPE_MLME; -} - -static inline bool fapi_is_ma(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SAP_TYPE_MASK) == FAPI_SAP_TYPE_MA; -} - -static inline bool fapi_is_debug(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SAP_TYPE_MASK) == FAPI_SAP_TYPE_DEBUG; -} - -static inline bool fapi_is_test(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SAP_TYPE_MASK) == FAPI_SAP_TYPE_TEST; -} - -static inline bool fapi_is_req(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SIG_TYPE_MASK) == FAPI_SIG_TYPE_REQ; -} - -static inline bool fapi_is_cfm(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SIG_TYPE_MASK) == FAPI_SIG_TYPE_CFM; -} - -static inline bool fapi_is_res(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SIG_TYPE_MASK) == FAPI_SIG_TYPE_RES; -} - -static inline bool fapi_is_ind(struct sk_buff *skb) -{ - return (fapi_get_sigid(skb) & FAPI_SIG_TYPE_MASK) == FAPI_SIG_TYPE_IND; -} - -static inline u16 fapi_get_expected_size_table(struct sk_buff *skb, const u16 fapi_size_table[], size_t table_size, u16 start_id) -{ - u16 id = fapi_get_sigid(skb); - - if (id < start_id) - return 0; - - if (id - start_id >= (u16)table_size) - return 0; - - return fapi_size_table[id - start_id]; -} - -static inline u16 fapi_get_expected_size(struct sk_buff *skb) -{ - static const u16 fapi_ma_req_size_table[] = { - fapi_sig_size(ma_unitdata_req), - 0, - fapi_sig_size(ma_spare_1_req), - fapi_sig_size(ma_spare_2_req), - fapi_sig_size(ma_spare_3_req), - fapi_sig_size(ma_spare_signal_1_req), - fapi_sig_size(ma_spare_signal_2_req), - fapi_sig_size(ma_spare_signal_3_req), - }; - - static const u16 fapi_mlme_req_size_table[] = { - fapi_sig_size(mlme_get_req), - fapi_sig_size(mlme_set_req), - fapi_sig_size(mlme_powermgt_req), - fapi_sig_size(mlme_add_info_elements_req), - fapi_sig_size(mlme_add_scan_req), - fapi_sig_size(mlme_del_scan_req), - fapi_sig_size(mlme_add_vif_req), - fapi_sig_size(mlme_del_vif_req), - fapi_sig_size(mlme_start_req), - fapi_sig_size(mlme_set_channel_req), - fapi_sig_size(mlme_connect_req), - fapi_sig_size(mlme_reassociate_req), - fapi_sig_size(mlme_roam_req), - fapi_sig_size(mlme_disconnect_req), - fapi_sig_size(mlme_register_action_frame_req), - fapi_sig_size(mlme_send_frame_req), - fapi_sig_size(mlme_reset_dwell_time_req), - fapi_sig_size(mlme_set_traffic_parameters_req), - fapi_sig_size(mlme_del_traffic_parameters_req), - fapi_sig_size(mlme_set_packet_filter_req), - fapi_sig_size(mlme_set_ip_address_req), - fapi_sig_size(mlme_set_acl_req), - 0, - fapi_sig_size(mlme_setkeys_req), - 0, - fapi_sig_size(mlme_get_key_sequence_req), - 0, - fapi_sig_size(mlme_set_pmk_req), - 0, - 0, - fapi_sig_size(mlme_set_cached_channels_req), - fapi_sig_size(mlme_set_whitelist_ssid_req), - fapi_sig_size(mlme_tdls_action_req), - fapi_sig_size(mlme_channel_switch_req), - fapi_sig_size(mlme_monitor_rssi_req), - fapi_sig_size(mlme_start_link_statistics_req), - fapi_sig_size(mlme_stop_link_statistics_req), - 0, - fapi_sig_size(mlme_set_pno_list_req), - fapi_sig_size(mlme_host_state_req), - fapi_sig_size(mlme_add_range_req), - fapi_sig_size(mlme_del_range_req), - fapi_sig_size(mlme_set_noa_req), - fapi_sig_size(mlme_set_ctwindow_req), - fapi_sig_size(mlme_nan_start_req), - fapi_sig_size(mlme_nan_config_req), - fapi_sig_size(mlme_nan_publish_req), - fapi_sig_size(mlme_nan_subscribe_req), - fapi_sig_size(mlme_nan_followup_req), - fapi_sig_size(mlme_unset_channel_req), - fapi_sig_size(mlme_set_country_req), - fapi_sig_size(mlme_forward_beacon_req), - fapi_sig_size(mlme_ndp_request_req), - fapi_sig_size(mlme_ndp_response_req), - fapi_sig_size(mlme_ndp_terminate_req), - 0, - 0, - fapi_sig_size(mlme_spare_4_req), - fapi_sig_size(mlme_spare_5_req), - fapi_sig_size(mlme_spare_6_req), - fapi_sig_size(mlme_install_apf_req), - fapi_sig_size(mlme_read_apf_req), - fapi_sig_size(mlme_set_num_antennas_req), - fapi_sig_size(mlme_arp_detect_req), - fapi_sig_size(mlme_spare_signal_1_req), - fapi_sig_size(mlme_spare_signal_2_req), - fapi_sig_size(mlme_spare_signal_3_req), - }; - - static const u16 fapi_debug_req_size_table[] = { - fapi_sig_size(debug_spare_1_req), - fapi_sig_size(debug_spare_2_req), - fapi_sig_size(debug_spare_3_req), - fapi_sig_size(debug_spare_signal_1_req), - fapi_sig_size(debug_spare_signal_2_req), - fapi_sig_size(debug_spare_signal_3_req), - }; - - static const u16 fapi_test_req_size_table[] = { - fapi_sig_size(test_block_requests_req), - fapi_sig_size(test_panic_req), - fapi_sig_size(test_suspend_req), - fapi_sig_size(test_resume_req), - fapi_sig_size(radio_logging_req), - fapi_sig_size(wlanlite_cw_start_req), - fapi_sig_size(wlanlite_cw_stop_req), - fapi_sig_size(wlanlite_tx_set_params_req), - fapi_sig_size(wlanlite_tx_start_req), - fapi_sig_size(wlanlite_tx_read_req), - fapi_sig_size(wlanlite_tx_stop_req), - fapi_sig_size(wlanlite_rx_start_req), - fapi_sig_size(wlanlite_rx_read_req), - fapi_sig_size(wlanlite_rx_stop_req), - fapi_sig_size(wlanlite_status_req), - fapi_sig_size(test_pmalloc_req), - fapi_sig_size(test_configure_monitor_mode_req), - 0, - fapi_sig_size(test_check_fw_alive_req), - fapi_sig_size(debug_generic_req), - fapi_sig_size(debug_pkt_sink_start_req), - fapi_sig_size(debug_pkt_sink_stop_req), - fapi_sig_size(debug_pkt_sink_report_req), - fapi_sig_size(debug_pkt_gen_start_req), - fapi_sig_size(debug_pkt_gen_stop_req), - fapi_sig_size(debug_pkt_gen_report_req), - fapi_sig_size(wlanlite_radio_select_req), - fapi_sig_size(test_hip_tester_start_req), - fapi_sig_size(test_hip_tester_stop_req), - fapi_sig_size(test_hip_tester_set_params_req), - fapi_sig_size(test_hip_tester_report_req), - fapi_sig_size(test_bist_get_tx_gain_req), - fapi_sig_size(test_spare_1_req), - fapi_sig_size(test_spare_2_req), - fapi_sig_size(test_spare_3_req), - fapi_sig_size(test_spare_signal_1_req), - fapi_sig_size(test_spare_signal_2_req), - fapi_sig_size(test_spare_signal_3_req), - }; - - static const u16 fapi_ma_cfm_size_table[] = { - fapi_sig_size(ma_unitdata_cfm), - 0, - fapi_sig_size(ma_spare_1_cfm), - fapi_sig_size(ma_spare_2_cfm), - fapi_sig_size(ma_spare_3_cfm), - fapi_sig_size(ma_spare_signal_1_cfm), - fapi_sig_size(ma_spare_signal_2_cfm), - fapi_sig_size(ma_spare_signal_3_cfm), - }; - - static const u16 fapi_mlme_cfm_size_table[] = { - fapi_sig_size(mlme_get_cfm), - fapi_sig_size(mlme_set_cfm), - fapi_sig_size(mlme_powermgt_cfm), - fapi_sig_size(mlme_add_info_elements_cfm), - fapi_sig_size(mlme_add_scan_cfm), - fapi_sig_size(mlme_del_scan_cfm), - fapi_sig_size(mlme_add_vif_cfm), - fapi_sig_size(mlme_del_vif_cfm), - fapi_sig_size(mlme_start_cfm), - fapi_sig_size(mlme_set_channel_cfm), - fapi_sig_size(mlme_connect_cfm), - fapi_sig_size(mlme_reassociate_cfm), - fapi_sig_size(mlme_roam_cfm), - fapi_sig_size(mlme_disconnect_cfm), - fapi_sig_size(mlme_register_action_frame_cfm), - fapi_sig_size(mlme_send_frame_cfm), - fapi_sig_size(mlme_reset_dwell_time_cfm), - fapi_sig_size(mlme_set_traffic_parameters_cfm), - fapi_sig_size(mlme_del_traffic_parameters_cfm), - fapi_sig_size(mlme_set_packet_filter_cfm), - fapi_sig_size(mlme_set_ip_address_cfm), - fapi_sig_size(mlme_set_acl_cfm), - 0, - fapi_sig_size(mlme_setkeys_cfm), - 0, - fapi_sig_size(mlme_get_key_sequence_cfm), - 0, - fapi_sig_size(mlme_set_pmk_cfm), - 0, - 0, - fapi_sig_size(mlme_set_cached_channels_cfm), - fapi_sig_size(mlme_set_whitelist_ssid_cfm), - fapi_sig_size(mlme_tdls_action_cfm), - fapi_sig_size(mlme_channel_switch_cfm), - fapi_sig_size(mlme_monitor_rssi_cfm), - fapi_sig_size(mlme_start_link_statistics_cfm), - fapi_sig_size(mlme_stop_link_statistics_cfm), - 0, - fapi_sig_size(mlme_set_pno_list_cfm), - fapi_sig_size(mlme_host_state_cfm), - fapi_sig_size(mlme_add_range_cfm), - fapi_sig_size(mlme_del_range_cfm), - fapi_sig_size(mlme_set_noa_cfm), - fapi_sig_size(mlme_set_ctwindow_cfm), - fapi_sig_size(mlme_nan_start_cfm), - fapi_sig_size(mlme_nan_config_cfm), - fapi_sig_size(mlme_nan_publish_cfm), - fapi_sig_size(mlme_nan_subscribe_cfm), - fapi_sig_size(mlme_nan_followup_cfm), - fapi_sig_size(mlme_unset_channel_cfm), - fapi_sig_size(mlme_set_country_cfm), - fapi_sig_size(mlme_forward_beacon_cfm), - fapi_sig_size(mlme_ndp_request_cfm), - fapi_sig_size(mlme_ndp_response_cfm), - fapi_sig_size(mlme_ndp_terminate_cfm), - 0, - 0, - fapi_sig_size(mlme_spare_4_cfm), - fapi_sig_size(mlme_spare_5_cfm), - fapi_sig_size(mlme_spare_6_cfm), - fapi_sig_size(mlme_install_apf_cfm), - fapi_sig_size(mlme_read_apf_cfm), - fapi_sig_size(mlme_set_num_antennas_cfm), - fapi_sig_size(mlme_arp_detect_cfm), - fapi_sig_size(mlme_spare_signal_1_cfm), - fapi_sig_size(mlme_spare_signal_2_cfm), - fapi_sig_size(mlme_spare_signal_3_cfm), - }; - - static const u16 fapi_debug_cfm_size_table[] = { - fapi_sig_size(debug_spare_1_cfm), - fapi_sig_size(debug_spare_2_cfm), - fapi_sig_size(debug_spare_3_cfm), - fapi_sig_size(debug_spare_signal_1_cfm), - fapi_sig_size(debug_spare_signal_2_cfm), - fapi_sig_size(debug_spare_signal_3_cfm), - }; - - static const u16 fapi_test_cfm_size_table[] = { - fapi_sig_size(radio_logging_cfm), - fapi_sig_size(wlanlite_cw_start_cfm), - fapi_sig_size(wlanlite_tx_set_params_cfm), - fapi_sig_size(wlanlite_cw_stop_cfm), - fapi_sig_size(wlanlite_tx_start_cfm), - fapi_sig_size(wlanlite_tx_read_cfm), - fapi_sig_size(wlanlite_tx_stop_cfm), - fapi_sig_size(wlanlite_rx_start_cfm), - fapi_sig_size(wlanlite_rx_read_cfm), - fapi_sig_size(wlanlite_rx_stop_cfm), - fapi_sig_size(wlanlite_status_cfm), - fapi_sig_size(test_pmalloc_cfm), - fapi_sig_size(test_configure_monitor_mode_cfm), - 0, - fapi_sig_size(test_check_fw_alive_cfm), - fapi_sig_size(test_suspend_cfm), - fapi_sig_size(test_resume_cfm), - fapi_sig_size(debug_generic_cfm), - fapi_sig_size(wlanlite_radio_select_cfm), - fapi_sig_size(test_hip_tester_start_cfm), - fapi_sig_size(test_hip_tester_stop_cfm), - fapi_sig_size(test_hip_tester_set_params_cfm), - fapi_sig_size(test_bist_get_tx_gain_cfm), - fapi_sig_size(test_spare_1_cfm), - fapi_sig_size(test_spare_2_cfm), - fapi_sig_size(test_spare_3_cfm), - fapi_sig_size(test_spare_signal_1_cfm), - fapi_sig_size(test_spare_signal_2_cfm), - fapi_sig_size(test_spare_signal_3_cfm), - }; - - static const u16 fapi_ma_ind_size_table[] = { - fapi_sig_size(ma_unitdata_ind), - fapi_sig_size(ma_blockack_ind), - fapi_sig_size(ma_spare_1_ind), - fapi_sig_size(ma_spare_2_ind), - fapi_sig_size(ma_spare_3_ind), - fapi_sig_size(ma_spare_signal_1_ind), - fapi_sig_size(ma_spare_signal_2_ind), - fapi_sig_size(ma_spare_signal_3_ind), - }; - - static const u16 fapi_mlme_ind_size_table[] = { - fapi_sig_size(mlme_scan_ind), - fapi_sig_size(mlme_scan_done_ind), - fapi_sig_size(mlme_listen_end_ind), - fapi_sig_size(mlme_connect_ind), - fapi_sig_size(mlme_connected_ind), - fapi_sig_size(mlme_reassociate_ind), - fapi_sig_size(mlme_roam_ind), - fapi_sig_size(mlme_roamed_ind), - fapi_sig_size(mlme_disconnect_ind), - fapi_sig_size(mlme_disconnected_ind), - fapi_sig_size(mlme_procedure_started_ind), - fapi_sig_size(mlme_mic_failure_ind), - fapi_sig_size(mlme_frame_transmission_ind), - fapi_sig_size(mlme_received_frame_ind), - 0, - fapi_sig_size(mlme_tdls_peer_ind), - 0, - 0, - fapi_sig_size(mlme_rssi_report_ind), - fapi_sig_size(mlme_ac_priority_update_ind), - fapi_sig_size(mlme_range_ind), - fapi_sig_size(mlme_range_done_ind), - fapi_sig_size(mlme_event_log_ind), - fapi_sig_size(mlme_nan_event_ind), - fapi_sig_size(mlme_nan_service_ind), - fapi_sig_size(mlme_nan_followup_ind), - fapi_sig_size(mlme_channel_switched_ind), - fapi_sig_size(mlme_synchronised_ind), - fapi_sig_size(mlme_beacon_reporting_event_ind), - fapi_sig_size(mlme_spare_3_ind), - fapi_sig_size(mlme_spare_4_ind), - fapi_sig_size(mlme_ndp_request_ind), - fapi_sig_size(mlme_ndp_requested_ind), - fapi_sig_size(mlme_ndp_response_ind), - fapi_sig_size(mlme_ndp_terminate_ind), - fapi_sig_size(mlme_ndp_terminated_ind), - fapi_sig_size(mlme_spare_5_ind), - fapi_sig_size(mlme_spare_signal_1_ind), - fapi_sig_size(mlme_spare_signal_2_ind), - fapi_sig_size(mlme_spare_signal_3_ind), - }; - - static const u16 fapi_debug_ind_size_table[] = { - fapi_sig_size(debug_word12_ind), - fapi_sig_size(debug_fault_ind), - fapi_sig_size(debug_words_ind), - fapi_sig_size(debug_spare_2_ind), - fapi_sig_size(debug_spare_3_ind), - fapi_sig_size(debug_spare_4_ind), - fapi_sig_size(debug_spare_signal_1_ind), - fapi_sig_size(debug_spare_signal_2_ind), - fapi_sig_size(debug_spare_signal_3_ind), - }; - - static const u16 fapi_test_ind_size_table[] = { - fapi_sig_size(radio_logging_ind), - fapi_sig_size(debug_generic_ind), - fapi_sig_size(debug_pkt_sink_report_ind), - fapi_sig_size(debug_pkt_gen_report_ind), - fapi_sig_size(test_hip_tester_report_ind), - fapi_sig_size(test_spare_1_ind), - fapi_sig_size(test_spare_2_ind), - fapi_sig_size(test_spare_3_ind), - fapi_sig_size(test_spare_signal_1_ind), - fapi_sig_size(test_spare_signal_2_ind), - fapi_sig_size(test_spare_signal_3_ind), - }; - - static const u16 fapi_mlme_res_size_table[] = { - fapi_sig_size(mlme_connect_res), - fapi_sig_size(mlme_connected_res), - fapi_sig_size(mlme_reassociate_res), - fapi_sig_size(mlme_roamed_res), - fapi_sig_size(mlme_tdls_peer_res), - fapi_sig_size(mlme_synchronised_res), - fapi_sig_size(mlme_spare_2_res), - fapi_sig_size(mlme_spare_3_res), - fapi_sig_size(mlme_spare_4_res), - fapi_sig_size(mlme_spare_signal_1_res), - fapi_sig_size(mlme_spare_signal_2_res), - fapi_sig_size(mlme_spare_signal_3_res), - }; - - static const u16 fapi_ma_res_size_table[] = { - fapi_sig_size(ma_spare_1_res), - fapi_sig_size(ma_spare_2_res), - fapi_sig_size(ma_spare_3_res), - fapi_sig_size(ma_spare_signal_1_res), - fapi_sig_size(ma_spare_signal_2_res), - fapi_sig_size(ma_spare_signal_3_res), - }; - - static const u16 fapi_debug_res_size_table[] = { - fapi_sig_size(debug_spare_1_res), - fapi_sig_size(debug_spare_2_res), - fapi_sig_size(debug_spare_3_res), - fapi_sig_size(debug_spare_signal_1_res), - fapi_sig_size(debug_spare_signal_2_res), - fapi_sig_size(debug_spare_signal_3_res), - }; - - static const u16 fapi_test_res_size_table[] = { - fapi_sig_size(test_spare_1_res), - fapi_sig_size(test_spare_2_res), - fapi_sig_size(test_spare_3_res), - fapi_sig_size(test_spare_signal_1_res), - fapi_sig_size(test_spare_signal_2_res), - fapi_sig_size(test_spare_signal_3_res), - }; - - if (fapi_is_mlme(skb) && fapi_is_req(skb)) - return fapi_get_expected_size_table(skb, fapi_mlme_req_size_table, ARRAY_SIZE(fapi_mlme_req_size_table), MLME_GET_REQ); - else if (fapi_is_mlme(skb) && fapi_is_cfm(skb)) - return fapi_get_expected_size_table(skb, fapi_mlme_cfm_size_table, ARRAY_SIZE(fapi_mlme_cfm_size_table), MLME_GET_CFM); - else if (fapi_is_mlme(skb) && fapi_is_res(skb)) - return fapi_get_expected_size_table(skb, fapi_mlme_res_size_table, ARRAY_SIZE(fapi_mlme_res_size_table), MLME_CONNECT_RES); - else if (fapi_is_mlme(skb) && fapi_is_ind(skb)) - return fapi_get_expected_size_table(skb, fapi_mlme_ind_size_table, ARRAY_SIZE(fapi_mlme_ind_size_table), MLME_SCAN_IND); - else if (fapi_is_ma(skb) && fapi_is_req(skb)) - return fapi_get_expected_size_table(skb, fapi_ma_req_size_table, ARRAY_SIZE(fapi_ma_req_size_table), MA_UNITDATA_REQ); - else if (fapi_is_ma(skb) && fapi_is_cfm(skb)) - return fapi_get_expected_size_table(skb, fapi_ma_cfm_size_table, ARRAY_SIZE(fapi_ma_cfm_size_table), MA_UNITDATA_CFM); - else if (fapi_is_ma(skb) && fapi_is_ind(skb)) - return fapi_get_expected_size_table(skb, fapi_ma_ind_size_table, ARRAY_SIZE(fapi_ma_ind_size_table), MA_UNITDATA_IND); - else if (fapi_is_debug(skb) && fapi_is_req(skb)) - return fapi_get_expected_size_table(skb, fapi_debug_req_size_table, ARRAY_SIZE(fapi_debug_req_size_table), DEBUG_GENERIC_REQ); - else if (fapi_is_debug(skb) && fapi_is_cfm(skb)) - return fapi_get_expected_size_table(skb, fapi_debug_cfm_size_table, ARRAY_SIZE(fapi_debug_cfm_size_table), DEBUG_GENERIC_CFM); - else if (fapi_is_debug(skb) && fapi_is_ind(skb)) - return fapi_get_expected_size_table(skb, fapi_debug_ind_size_table, ARRAY_SIZE(fapi_debug_ind_size_table), DEBUG_WORD12IND); - else if (fapi_is_test(skb) && fapi_is_req(skb)) - return fapi_get_expected_size_table(skb, fapi_test_req_size_table, ARRAY_SIZE(fapi_test_req_size_table), TEST_BLOCK_REQUESTS_REQ); - else if (fapi_is_test(skb) && fapi_is_cfm(skb)) - return fapi_get_expected_size_table(skb, fapi_test_cfm_size_table, ARRAY_SIZE(fapi_test_cfm_size_table), RADIO_LOGGING_CFM); - else if (fapi_is_test(skb) && fapi_is_ind(skb)) - return fapi_get_expected_size_table(skb, fapi_test_ind_size_table, ARRAY_SIZE(fapi_test_ind_size_table), RADIO_LOGGING_IND); - else if (fapi_is_mlme(skb) && fapi_is_res(skb)) - return fapi_get_expected_size_table(skb, fapi_ma_res_size_table, ARRAY_SIZE(fapi_ma_res_size_table), MA_SPARE_SIGNAL_1_RES); - else if (fapi_is_mlme(skb) && fapi_is_res(skb)) - return fapi_get_expected_size_table(skb, fapi_debug_res_size_table, ARRAY_SIZE(fapi_debug_res_size_table), DEBUG_SPARE_SIGNAL_1_RES); - else if (fapi_is_mlme(skb) && fapi_is_res(skb)) - return fapi_get_expected_size_table(skb, fapi_test_res_size_table, ARRAY_SIZE(fapi_test_res_size_table), TEST_SPARE_SIGNAL_1_RES); - - return 0; -} - -#ifdef __cplusplus -} -#endif -#endif /* _FAPI_H__ */ diff --git a/drivers/net/wireless/scsc/fw_test.c b/drivers/net/wireless/scsc/fw_test.c deleted file mode 100755 index f3ef2d6b771d..000000000000 --- a/drivers/net/wireless/scsc/fw_test.c +++ /dev/null @@ -1,978 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ -#include -#include -#include "dev.h" -#include "fapi.h" -#include "fw_test.h" -#include "debug.h" -#include "mgt.h" -#include "mlme.h" -#include "netif.h" -#include "ba.h" -#include "sap_mlme.h" - -static void slsi_fw_test_save_frame(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *saved_skbs[CONFIG_SCSC_WLAN_MAX_INTERFACES + 1], struct sk_buff *skb, bool udi_header) -{ - u16 vif; - - skb = slsi_skb_copy(skb, GFP_KERNEL); - - if (udi_header) - skb_pull(skb, sizeof(struct udi_msg_t)); - - vif = fapi_get_vif(skb); - - SLSI_DBG3(sdev, SLSI_FW_TEST, "sig:0x%.4X, vif:%d\n", fapi_get_sigid(skb), vif); - slsi_debug_frame(sdev, NULL, skb, "SAVE"); - - slsi_spinlock_lock(&fwtest->fw_test_lock); - slsi_kfree_skb(saved_skbs[vif]); - saved_skbs[vif] = skb; - slsi_spinlock_unlock(&fwtest->fw_test_lock); -} - -static void slsi_fw_test_process_frame(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb, bool udi_header) -{ - u16 vif; - - skb = slsi_skb_copy(skb, GFP_KERNEL); - - if (udi_header) - skb_pull(skb, sizeof(struct udi_msg_t)); - - vif = fapi_get_vif(skb); - - SLSI_DBG3(sdev, SLSI_FW_TEST, "sig:0x%.4X, vif:%d\n", fapi_get_sigid(skb), vif); - slsi_debug_frame(sdev, NULL, skb, "PROCESS"); - - slsi_skb_work_enqueue(&fwtest->fw_test_work, skb); -} - -int slsi_fw_test_signal(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - u16 vif = fapi_get_vif(skb); - - /* Atleast one write to via the UDI interface */ - fwtest->fw_test_enabled = true; - SLSI_DBG3(sdev, SLSI_FW_TEST, "0x%p: sig:0x%.4X, vif:%d\n", skb, fapi_get_sigid(skb), vif); - - if (WARN(vif > CONFIG_SCSC_WLAN_MAX_INTERFACES, "vif(%d) > CONFIG_SCSC_WLAN_MAX_INTERFACES", vif)) - return -EINVAL; - - switch (fapi_get_sigid(skb)) { - case MLME_ADD_VIF_REQ: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Save MLME_ADD_VIF_REQ(0x%.4X, vif:%d)\n", skb, fapi_get_sigid(skb), vif); - slsi_fw_test_save_frame(sdev, fwtest, fwtest->mlme_add_vif_req, skb, false); - slsi_fw_test_process_frame(sdev, fwtest, skb, false); - break; - case MLME_CONNECT_REQ: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Save MLME_CONNECT_REQ(0x%.4X, vif:%d)\n", skb, fapi_get_sigid(skb), vif); - slsi_fw_test_save_frame(sdev, fwtest, fwtest->mlme_connect_req, skb, false); - break; - case MLME_DEL_VIF_REQ: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Save MLME_DEL_VIF_REQ(0x%.4X, vif:%d)\n", skb, fapi_get_sigid(skb), vif); - slsi_fw_test_process_frame(sdev, fwtest, skb, false); - break; - default: - return 0; - } - - return 0; -} - -int slsi_fw_test_signal_with_udi_header(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct udi_msg_t *udi_msg = (struct udi_msg_t *)skb->data; - struct fapi_vif_signal_header *fapi_header = (struct fapi_vif_signal_header *)(skb->data + sizeof(struct udi_msg_t)); - - if (!fwtest->fw_test_enabled) - return 0; - - SLSI_DBG3(sdev, SLSI_FW_TEST, "0x%p: sig:0x%.4X, vif:%d\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - - if (udi_msg->direction == SLSI_LOG_DIRECTION_TO_HOST) { - switch (le16_to_cpu(fapi_header->id)) { - case MLME_DISCONNECT_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_DISCONNECT_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - case MLME_DISCONNECTED_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_DISCONNECTED_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - case MLME_CONNECT_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_CONNECT_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - case MLME_CONNECTED_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_CONNECTED_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - case MLME_ROAMED_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_ROAMED_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - case MLME_TDLS_PEER_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_TDLS_PEER_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - case MLME_CONNECT_CFM: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Save MLME_CONNECT_CFM(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_save_frame(sdev, fwtest, fwtest->mlme_connect_cfm, skb, true); - break; - case MLME_PROCEDURE_STARTED_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Save MLME_PROCEDURE_STARTED_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_save_frame(sdev, fwtest, fwtest->mlme_procedure_started_ind, skb, true); - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_PROCEDURE_STARTED_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - case MLME_START_CFM: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MLME_START_CFM(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - sdev->device_config.ap_disconnect_ind_timeout = SLSI_DEFAULT_AP_DISCONNECT_IND_TIMEOUT; - break; - case MA_BLOCKACK_IND: - SLSI_DBG2(sdev, SLSI_FW_TEST, "0x%p: Process MA_BLOCKACK_IND(0x%.4X, vif:%d)\n", skb, le16_to_cpu(fapi_header->id), le16_to_cpu(fapi_header->vif)); - slsi_fw_test_process_frame(sdev, fwtest, skb, true); - break; - default: - break; - } - } - - return 0; -} - -static void slsi_fw_test_connect_station_roam(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - struct sk_buff *mlme_procedure_started_ind; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Connect(vif:%d) Roam\n", ndev_vif->ifnum); - - if (WARN(!ndev_vif->is_fw_test, "!is_fw_test")) - return; - - if (WARN(!ndev_vif->activated, "Not Activated")) - return; - - if (WARN(ndev_vif->vif_type != FAPI_VIFTYPE_STATION, "Not Station Vif")) - return; - - if (WARN(!peer, "peer not found")) - return; - - slsi_spinlock_lock(&fwtest->fw_test_lock); - mlme_procedure_started_ind = fwtest->mlme_procedure_started_ind[ndev_vif->ifnum]; - fwtest->mlme_procedure_started_ind[ndev_vif->ifnum] = NULL; - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - if (WARN(!mlme_procedure_started_ind, "mlme_procedure_started_ind not found")) - return; - - slsi_rx_ba_stop_all(dev, peer); - - SLSI_ETHER_COPY(peer->address, mgmt->bssid); - slsi_peer_update_assoc_req(sdev, dev, peer, mlme_procedure_started_ind); - slsi_peer_update_assoc_rsp(sdev, dev, peer, slsi_skb_copy(skb, GFP_KERNEL)); -} - -static void slsi_fw_test_connect_start_station(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - struct sk_buff *ind; - struct slsi_peer *peer; - u8 bssid[ETH_ALEN]; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Connect Start(vif:%d)\n", ndev_vif->ifnum); - - if (WARN(!ndev_vif->is_fw_test, "!is_fw_test")) - return; - if (WARN(ndev_vif->activated, "Already Activated")) - return; - - slsi_spinlock_lock(&fwtest->fw_test_lock); - req = fwtest->mlme_connect_req[ndev_vif->ifnum]; - cfm = fwtest->mlme_connect_cfm[ndev_vif->ifnum]; - ind = fwtest->mlme_procedure_started_ind[ndev_vif->ifnum]; - if (req) - SLSI_ETHER_COPY(bssid, fapi_get_buff(req, u.mlme_connect_req.bssid)); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - if (WARN(!req, "mlme_connect_req Not found")) - return; - if (WARN(!cfm, "mlme_connect_cfm Not found")) - return; - - ndev_vif->iftype = NL80211_IFTYPE_STATION; - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - ndev_vif->vif_type = FAPI_VIFTYPE_STATION; - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d slsi_vif_activated\n", ndev_vif->ifnum); - if (WARN(slsi_vif_activated(sdev, dev) != 0, "slsi_vif_activated() Failed")) - return; - - peer = slsi_peer_add(sdev, dev, bssid, SLSI_STA_PEER_QUEUESET + 1); - if (WARN(!peer, "slsi_peer_add(%pM) Failed", bssid)) { - slsi_vif_deactivated(sdev, dev); - return; - } - - slsi_peer_update_assoc_req(sdev, dev, peer, slsi_skb_copy(skb, GFP_KERNEL)); -} - -static void slsi_fw_test_connect_station(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - struct sk_buff *ind; - struct slsi_peer *peer; - u16 result; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Connect(vif:%d)\n", ndev_vif->ifnum); - - if (WARN(!ndev_vif->is_fw_test, "!is_fw_test")) - return; - - result = fapi_get_u16(skb, u.mlme_connect_ind.result_code); - - slsi_spinlock_lock(&fwtest->fw_test_lock); - req = fwtest->mlme_connect_req[ndev_vif->ifnum]; - cfm = fwtest->mlme_connect_cfm[ndev_vif->ifnum]; - ind = fwtest->mlme_procedure_started_ind[ndev_vif->ifnum]; - fwtest->mlme_connect_req[ndev_vif->ifnum] = NULL; - fwtest->mlme_connect_cfm[ndev_vif->ifnum] = NULL; - fwtest->mlme_procedure_started_ind[ndev_vif->ifnum] = NULL; - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - if (WARN(!req, "mlme_connect_req Not found")) - goto exit; - if (WARN(!cfm, "mlme_connect_cfm Not found")) - goto exit; - if (FAPI_RESULTCODE_SUCCESS == result && - WARN(!ind, "mlme_procedure_started_ind Not found")) - goto exit; - if (FAPI_RESULTCODE_SUCCESS != result) - goto exit; - - if (WARN(!ndev_vif->activated, "Not Activated")) - return; - - peer = slsi_get_peer_from_mac(sdev, dev, fapi_get_buff(req, u.mlme_connect_req.bssid)); - if (WARN(!peer, "slsi_get_peer_from_mac(%pM) Failed", fapi_get_buff(req, u.mlme_connect_req.bssid))) - goto exit; - - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - netif_carrier_on(dev); - -exit: - slsi_kfree_skb(req); - slsi_kfree_skb(cfm); - slsi_kfree_skb(ind); -} - -static void slsi_fw_test_started_network(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 result = fapi_get_u16(skb, u.mlme_start_cfm.result_code); - - SLSI_UNUSED_PARAMETER(fwtest); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Start Network(vif:%d)\n", ndev_vif->ifnum); - - if (WARN(!ndev_vif->is_fw_test, "!is_fw_test")) - return; - if (WARN(ndev_vif->activated, "Already Activated")) - return; - - ndev_vif->iftype = NL80211_IFTYPE_AP; - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_AP; - ndev_vif->vif_type = FAPI_VIFTYPE_AP; - - if (WARN(slsi_vif_activated(sdev, dev) != 0, "slsi_vif_activated() Failed")) - return; - - if (FAPI_RESULTCODE_SUCCESS == result) - netif_carrier_on(dev); -} - -static void slsi_fw_test_stop_network(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_UNUSED_PARAMETER(fwtest); - SLSI_UNUSED_PARAMETER(skb); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (!ndev_vif->is_fw_test) - return; - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Stopping Network(vif:%d)\n", ndev_vif->ifnum); - - if (WARN(!ndev_vif->activated, "Not Activated")) - return; - - netif_carrier_off(dev); - slsi_vif_deactivated(sdev, dev); -} - -static void slsi_fw_test_connect_start_ap(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = NULL; - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - u16 peer_index; - - SLSI_UNUSED_PARAMETER(fwtest); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Connect Start(vif:%d)\n", ndev_vif->ifnum); - WARN(!ndev_vif->is_fw_test, "!is_fw_test"); - - if (WARN(!ndev_vif->activated, "Not Activated")) - return; - - if (WARN_ON(!ieee80211_is_assoc_req(mgmt->frame_control) && - !ieee80211_is_reassoc_req(mgmt->frame_control))) - return; - peer_index = fapi_get_u16(skb, u.mlme_procedure_started_ind.association_identifier); - - peer = slsi_peer_add(sdev, dev, mgmt->sa, peer_index); - if (WARN_ON(!peer)) - return; - - slsi_peer_update_assoc_req(sdev, dev, peer, slsi_skb_copy(skb, GFP_KERNEL)); - peer->connected_state = SLSI_STA_CONN_STATE_CONNECTING; -} - -static void slsi_fw_test_connected_network(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = NULL; - u16 aid = fapi_get_u16(skb, u.mlme_connected_ind.association_identifier); - - SLSI_UNUSED_PARAMETER(fwtest); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Connect(vif:%d, aid:%d)\n", ndev_vif->ifnum, aid); - WARN(!ndev_vif->is_fw_test, "!is_fw_test"); - - if (WARN(!ndev_vif->activated, "Not Activated")) - return; - - if (WARN_ON(aid > SLSI_PEER_INDEX_MAX)) - return; - - peer = slsi_get_peer_from_qs(sdev, dev, aid - 1); - if (WARN(!peer, "Peer(aid:%d) Not Found", aid)) - return; - - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - peer->connected_state = SLSI_STA_CONN_STATE_CONNECTED; - - slsi_rx_buffered_frames(sdev, dev, peer); -} - -/* Setup the NetDev / Peers based on the saved frames */ -static void slsi_fw_test_procedure_started_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 viftype = FAPI_VIFTYPE_STATION; - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "ProceedureStarted(vif:%d)\n", ndev_vif->ifnum); - - if (fapi_get_u16(skb, u.mlme_procedure_started_ind.procedure_type) != FAPI_PROCEDURETYPE_CONNECTION_STARTED) { - slsi_kfree_skb(skb); - return; - } - - /* Set up the VIF and Data plane ready to go BUT do not open the control port */ - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Start UDI test NetDevice(vif:%d)\n", ndev_vif->ifnum); - if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL")) - goto out; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - switch (viftype) { - case FAPI_VIFTYPE_STATION: - slsi_fw_test_connect_start_station(sdev, dev, fwtest, skb); - break; - case FAPI_VIFTYPE_AP: - slsi_fw_test_connect_start_ap(sdev, dev, fwtest, skb); - break; - default: - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype); - break; - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - -out: - slsi_kfree_skb(skb); -} - -/* Setup the NetDev / Peers based on the saved frames */ -static void slsi_fw_test_connect_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 viftype = FAPI_VIFTYPE_STATION; - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Connect(vif:%d)\n", ndev_vif->ifnum); - - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Start UDI test NetDevice(vif:%d)\n", ndev_vif->ifnum); - if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL")) - goto out; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - switch (viftype) { - case FAPI_VIFTYPE_STATION: - slsi_fw_test_connect_station(sdev, dev, fwtest, skb); - break; - default: - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype); - break; - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - -out: - slsi_kfree_skb(skb); -} - -static void slsi_fw_test_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 viftype = FAPI_VIFTYPE_STATION; - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Connected(vif:%d)\n", ndev_vif->ifnum); - - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL")) - goto out; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - switch (viftype) { - case FAPI_VIFTYPE_AP: - slsi_fw_test_connected_network(sdev, dev, fwtest, skb); - break; - default: - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype); - break; - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - -out: - slsi_kfree_skb(skb); -} - -static void slsi_fw_test_roamed_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 viftype = FAPI_VIFTYPE_STATION; - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Roamed(vif:%d)\n", ndev_vif->ifnum); - - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL")) - goto out; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - switch (viftype) { - case FAPI_VIFTYPE_STATION: - slsi_fw_test_connect_station_roam(sdev, dev, fwtest, skb); - break; - default: - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype); - break; - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - -out: - slsi_kfree_skb(skb); -} - -static void slsi_fw_test_disconnect_station(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - - SLSI_UNUSED_PARAMETER(fwtest); - SLSI_UNUSED_PARAMETER(skb); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (!ndev_vif->is_fw_test) - return; - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Disconnect(vif:%d)\n", ndev_vif->ifnum); - - if (WARN(!ndev_vif->activated, "Not Activated")) - return; - - netif_carrier_off(dev); - if (peer) { - slsi_spinlock_lock(&ndev_vif->peer_lock); - slsi_peer_remove(sdev, dev, peer); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - } - slsi_vif_deactivated(sdev, dev); -} - -static void slsi_fw_test_disconnect_network(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - /* Find the peer based on MAC address, mlme-disconnect-ind and mlme-disconnected-ind - * both have the MAC address in the same position. - */ - struct slsi_peer *peer = slsi_get_peer_from_mac(sdev, dev, fapi_get_buff(skb, u.mlme_disconnect_ind.peer_sta_address)); - - SLSI_UNUSED_PARAMETER(fwtest); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (!ndev_vif->is_fw_test) - return; - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Disconnect(vif:%d)\n", ndev_vif->ifnum); - - if (peer) { - slsi_spinlock_lock(&ndev_vif->peer_lock); - slsi_peer_remove(sdev, dev, peer); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - } -} - -static void slsi_fw_test_disconnected_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 viftype = FAPI_VIFTYPE_STATION; - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL")) - goto out; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - switch (viftype) { - case FAPI_VIFTYPE_STATION: - slsi_fw_test_disconnect_station(sdev, dev, fwtest, skb); - break; - case FAPI_VIFTYPE_AP: - slsi_fw_test_disconnect_network(sdev, dev, fwtest, skb); - break; - default: - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype); - break; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - -out: - slsi_kfree_skb(skb); -} - -static void slsi_fw_test_tdls_event_connected(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct slsi_peer *peer = NULL; - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 peer_index = fapi_get_u16(skb, u.mlme_tdls_peer_ind.peer_index); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - ndev_vif->sta.tdls_enabled = true; - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "TDLS connect (vif:%d, peer_index:%d, mac:%pM)\n", fapi_get_vif(skb), peer_index, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address)); - - if ((ndev_vif->sta.tdls_peer_sta_records) + 1 > SLSI_TDLS_PEER_CONNECTIONS_MAX) { - SLSI_NET_ERR(dev, "max TDLS limit reached (peer_index:%d)\n", peer_index); - goto out; - } - - if (peer_index < SLSI_TDLS_PEER_INDEX_MIN || peer_index > SLSI_TDLS_PEER_INDEX_MAX) { - SLSI_NET_ERR(dev, "incorrect index (peer_index:%d)\n", peer_index); - goto out; - } - - peer = slsi_peer_add(sdev, dev, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address), peer_index); - if (!peer) { - SLSI_NET_ERR(dev, "peer add failed\n"); - goto out; - } - - /* QoS is mandatory for TDLS - enable QoS for TDLS peer by default */ - peer->qos_enabled = true; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - - /* move TDLS packets from STA Q to TDLS Q */ - slsi_tdls_move_packets(sdev, dev, ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET], peer, true); - -out: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -static void slsi_fw_test_tdls_event_disconnected(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct slsi_peer *peer = NULL; - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_NET_DBG1(dev, SLSI_MLME, "TDLS dis-connect (vif:%d, mac:%pM)\n", ndev_vif->ifnum, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address)); - - slsi_spinlock_lock(&ndev_vif->peer_lock); - peer = slsi_get_peer_from_mac(sdev, dev, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address)); - if (!peer || (peer->aid == 0)) { - WARN_ON(!peer || (peer->aid == 0)); - SLSI_NET_DBG1(dev, SLSI_MLME, "can't find peer by MAC address\n"); - goto out; - } - - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - - /* move TDLS packets from TDLS Q to STA Q */ - slsi_tdls_move_packets(sdev, dev, ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET], peer, false); - slsi_peer_remove(sdev, dev, peer); -out: - slsi_spinlock_unlock(&ndev_vif->peer_lock); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -static void slsi_fw_test_tdls_peer_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 vif_type = 0; - u16 tdls_event; - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - if (WARN(!ndev_vif->activated, "Not Activated")) { - slsi_kfree_skb(skb); - return; - } - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - vif_type = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - if (WARN(vif_type != FAPI_VIFTYPE_STATION, "Not STA VIF")) { - slsi_kfree_skb(skb); - return; - } - - tdls_event = fapi_get_u16(skb, u.mlme_tdls_peer_ind.tdls_event); - SLSI_NET_DBG1(dev, SLSI_MLME, "TDLS peer(vif:%d tdls_event:%d)\n", ndev_vif->ifnum, tdls_event); - switch (tdls_event) { - case FAPI_TDLSEVENT_CONNECTED: - slsi_fw_test_tdls_event_connected(sdev, dev, skb); - break; - case FAPI_TDLSEVENT_DISCONNECTED: - slsi_fw_test_tdls_event_disconnected(sdev, dev, skb); - break; - case FAPI_TDLSEVENT_DISCOVERED: - /* nothing to do */ - break; - default: - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d tdls_event:%d not supported\n", ndev_vif->ifnum, tdls_event); - break; - } - slsi_kfree_skb(skb); -} - -/* Setup the NetDev */ -static void slsi_fw_test_start_cfm(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 viftype = FAPI_VIFTYPE_UNSYNCHRONISED; - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Start(vif:%d)\n", ndev_vif->ifnum); - - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Start UDI test NetDevice(vif:%d)\n", ndev_vif->ifnum); - if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL")) - goto out; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - switch (viftype) { - case FAPI_VIFTYPE_AP: - slsi_fw_test_started_network(sdev, dev, fwtest, skb); - break; - default: - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype); - break; - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - -out: - slsi_kfree_skb(skb); -} - -static void slsi_fw_test_add_vif_req(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_UNUSED_PARAMETER(sdev); - SLSI_UNUSED_PARAMETER(fwtest); - - SLSI_DBG1(sdev, SLSI_FW_TEST, "Mark UDI test NetDevice(vif:%d)\n", fapi_get_vif(skb)); - ndev_vif->is_fw_test = true; - slsi_kfree_skb(skb); -} - -static void slsi_fw_test_del_vif_req(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *add_vif_req; - u16 viftype = FAPI_VIFTYPE_UNSYNCHRONISED; - - SLSI_DBG1(sdev, SLSI_FW_TEST, "Unmark UDI test NetDevice(vif:%d)\n", fapi_get_vif(skb)); - - slsi_spinlock_lock(&fwtest->fw_test_lock); - add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum]; - if (add_vif_req) - viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type); - slsi_kfree_skb(fwtest->mlme_add_vif_req[ndev_vif->ifnum]); - slsi_kfree_skb(fwtest->mlme_connect_req[ndev_vif->ifnum]); - slsi_kfree_skb(fwtest->mlme_connect_cfm[ndev_vif->ifnum]); - slsi_kfree_skb(fwtest->mlme_procedure_started_ind[ndev_vif->ifnum]); - - fwtest->mlme_add_vif_req[ndev_vif->ifnum] = NULL; - fwtest->mlme_connect_req[ndev_vif->ifnum] = NULL; - fwtest->mlme_connect_cfm[ndev_vif->ifnum] = NULL; - fwtest->mlme_procedure_started_ind[ndev_vif->ifnum] = NULL; - slsi_spinlock_unlock(&fwtest->fw_test_lock); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - switch (viftype) { - /* As there is no specific MLME primitive for shutting down the network - * perform an actions on the MLME-DEL-VIF. - */ - case FAPI_VIFTYPE_AP: - slsi_fw_test_stop_network(sdev, dev, fwtest, skb); - break; - default: - if (ndev_vif->is_fw_test && ndev_vif->activated) { - netif_carrier_off(dev); - slsi_vif_deactivated(sdev, dev); - } - break; - } - ndev_vif->is_fw_test = false; - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - slsi_kfree_skb(skb); -} - -static void slsi_fw_test_ma_blockack_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_fw_test *fwtest, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - if (!ndev_vif->is_fw_test) { - slsi_kfree_skb(skb); - return; - } - - SLSI_NET_DBG1(dev, SLSI_FW_TEST, "MA Block Ack Indication(vif:%d)\n", ndev_vif->ifnum); - slsi_rx_blockack_ind(sdev, dev, skb); -} - -void slsi_fw_test_work(struct work_struct *work) -{ - struct slsi_fw_test *fw_test = container_of(work, struct slsi_fw_test, fw_test_work.work); - struct slsi_dev *sdev = fw_test->sdev; - struct sk_buff *skb = slsi_skb_work_dequeue(&fw_test->fw_test_work); - struct net_device *dev; - - while (skb) { - u16 vif = fapi_get_vif(skb); - - SLSI_DBG3(sdev, SLSI_FW_TEST, "0x%p: Signal:0x%.4X, vif:%d\n", skb, fapi_get_sigid(skb), vif); - - if (WARN(!vif, "!vif")) { - slsi_kfree_skb(skb); - skb = slsi_skb_work_dequeue(&fw_test->fw_test_work); - continue; - } - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - dev = slsi_get_netdev_locked(sdev, vif); - if (!dev) { - /* Just ignore the signal. This is valid in some error testing scenarios*/ - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - slsi_kfree_skb(skb); - skb = slsi_skb_work_dequeue(&fw_test->fw_test_work); - continue; - } - - switch (fapi_get_sigid(skb)) { - case MLME_PROCEDURE_STARTED_IND: - slsi_fw_test_procedure_started_ind(sdev, dev, fw_test, skb); - break; - case MLME_CONNECT_IND: - slsi_fw_test_connect_ind(sdev, dev, fw_test, skb); - break; - case MLME_ROAMED_IND: - slsi_fw_test_roamed_ind(sdev, dev, fw_test, skb); - break; - case MLME_CONNECTED_IND: - slsi_fw_test_connected_ind(sdev, dev, fw_test, skb); - break; - case MLME_DISCONNECT_IND: - case MLME_DISCONNECTED_IND: - slsi_fw_test_disconnected_ind(sdev, dev, fw_test, skb); - break; - case MLME_TDLS_PEER_IND: - slsi_fw_test_tdls_peer_ind(sdev, dev, fw_test, skb); - break; - case MLME_START_CFM: - slsi_fw_test_start_cfm(sdev, dev, fw_test, skb); - break; - case MLME_ADD_VIF_REQ: - slsi_fw_test_add_vif_req(sdev, dev, fw_test, skb); - break; - case MLME_DEL_VIF_REQ: - slsi_fw_test_del_vif_req(sdev, dev, fw_test, skb); - break; - case MA_BLOCKACK_IND: - slsi_fw_test_ma_blockack_ind(sdev, dev, fw_test, skb); - break; - default: - WARN(1, "Unhandled Signal"); - slsi_kfree_skb(skb); - break; - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - skb = slsi_skb_work_dequeue(&fw_test->fw_test_work); - } -} - -void slsi_fw_test_init(struct slsi_dev *sdev, struct slsi_fw_test *fwtest) -{ - SLSI_DBG1(sdev, SLSI_FW_TEST, "\n"); - memset(fwtest, 0x00, sizeof(struct slsi_fw_test)); - fwtest->sdev = sdev; - slsi_spinlock_create(&fwtest->fw_test_lock); - slsi_skb_work_init(sdev, NULL, &fwtest->fw_test_work, "slsi_wlan_fw_test", slsi_fw_test_work); -} - -void slsi_fw_test_deinit(struct slsi_dev *sdev, struct slsi_fw_test *fwtest) -{ - int i; - - SLSI_UNUSED_PARAMETER(sdev); - - SLSI_DBG1(sdev, SLSI_FW_TEST, "\n"); - fwtest->fw_test_enabled = false; - slsi_skb_work_deinit(&fwtest->fw_test_work); - slsi_spinlock_lock(&fwtest->fw_test_lock); - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) { - slsi_kfree_skb(fwtest->mlme_add_vif_req[i]); - slsi_kfree_skb(fwtest->mlme_connect_req[i]); - slsi_kfree_skb(fwtest->mlme_connect_cfm[i]); - slsi_kfree_skb(fwtest->mlme_procedure_started_ind[i]); - - fwtest->mlme_add_vif_req[i] = NULL; - fwtest->mlme_connect_req[i] = NULL; - fwtest->mlme_connect_cfm[i] = NULL; - fwtest->mlme_procedure_started_ind[i] = NULL; - } - slsi_spinlock_unlock(&fwtest->fw_test_lock); - memset(fwtest, 0x00, sizeof(struct slsi_fw_test)); -} diff --git a/drivers/net/wireless/scsc/fw_test.h b/drivers/net/wireless/scsc/fw_test.h deleted file mode 100755 index fa88d84a3383..000000000000 --- a/drivers/net/wireless/scsc/fw_test.h +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_FW_TEST_H__ -#define __SLSI_FW_TEST_H__ - -#include "dev.h" - -struct slsi_fw_test { - struct slsi_dev *sdev; - bool fw_test_enabled; - struct slsi_skb_work fw_test_work; - struct slsi_spinlock fw_test_lock; - struct sk_buff *mlme_add_vif_req[CONFIG_SCSC_WLAN_MAX_INTERFACES + 1]; - struct sk_buff *mlme_connect_req[CONFIG_SCSC_WLAN_MAX_INTERFACES + 1]; - struct sk_buff *mlme_connect_cfm[CONFIG_SCSC_WLAN_MAX_INTERFACES + 1]; - struct sk_buff *mlme_procedure_started_ind[CONFIG_SCSC_WLAN_MAX_INTERFACES + 1]; /* TODO_HARDMAC : Per AID as well as per vif */ -}; - -void slsi_fw_test_init(struct slsi_dev *sdev, struct slsi_fw_test *fwtest); -void slsi_fw_test_deinit(struct slsi_dev *sdev, struct slsi_fw_test *fwtest); -int slsi_fw_test_signal(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb); -int slsi_fw_test_signal_with_udi_header(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb); - -#endif /*__SLSI_FW_TEST_H__*/ diff --git a/drivers/net/wireless/scsc/hip.c b/drivers/net/wireless/scsc/hip.c deleted file mode 100755 index 1d957a82b0f6..000000000000 --- a/drivers/net/wireless/scsc/hip.c +++ /dev/null @@ -1,303 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include - -#include "hip.h" -#include "debug.h" -#include "procfs.h" -#include "sap.h" -#ifdef CONFIG_SCSC_SMAPPER -#include "hip4_smapper.h" -#endif - -/* SAP implementations container. Local and static to hip */ -static struct hip_sap { - struct sap_api *sap[SAP_TOTAL]; -} hip_sap_cont; - -/* Register SAP with HIP layer */ -int slsi_hip_sap_register(struct sap_api *sap_api) -{ - u8 class = sap_api->sap_class; - - if (class >= SAP_TOTAL) - return -ENODEV; - - hip_sap_cont.sap[class] = sap_api; - - return 0; -} - -/* UNregister SAP with HIP layer */ -int slsi_hip_sap_unregister(struct sap_api *sap_api) -{ - u8 class = sap_api->sap_class; - - if (class >= SAP_TOTAL) - return -ENODEV; - - hip_sap_cont.sap[class] = NULL; - - return 0; -} - -int slsi_hip_sap_setup(struct slsi_dev *sdev) -{ - /* Execute callbacks to intorm Supported version */ - u16 version = 0; - u32 conf_hip4_ver = 0; - - conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); - - /* We enforce that all the SAPs are registered at this point */ - if ((!hip_sap_cont.sap[SAP_MLME]) || (!hip_sap_cont.sap[SAP_MA]) || - (!hip_sap_cont.sap[SAP_DBG]) || (!hip_sap_cont.sap[SAP_TST])) - return -ENODEV; - - if (hip_sap_cont.sap[SAP_MLME]->sap_version_supported) { - if (conf_hip4_ver == 4) - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_mlme_ver); - if (conf_hip4_ver == 5) - version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_mlme_ver); - if (hip_sap_cont.sap[SAP_MLME]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - if (hip_sap_cont.sap[SAP_MA]->sap_version_supported) { - if (conf_hip4_ver == 4) - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_ma_ver); - if (conf_hip4_ver == 5) - version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_ma_ver); - if (hip_sap_cont.sap[SAP_MA]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - if (hip_sap_cont.sap[SAP_DBG]->sap_version_supported) { - if (conf_hip4_ver == 4) - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_debug_ver); - if (conf_hip4_ver == 5) - version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_debug_ver); - if (hip_sap_cont.sap[SAP_DBG]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - if (hip_sap_cont.sap[SAP_TST]->sap_version_supported) { - if (conf_hip4_ver == 4) - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_test_ver); - if (conf_hip4_ver == 5) - version = scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_test_ver); - if (hip_sap_cont.sap[SAP_TST]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - /* Success */ - return 0; -} - -static int slsi_hip_service_notifier(struct notifier_block *nb, unsigned long event, void *data) -{ - struct slsi_dev *sdev = (struct slsi_dev *)data; - int i; - - if (!sdev) - return NOTIFY_BAD; - - /* We enforce that all the SAPs are registered at this point */ - if ((!hip_sap_cont.sap[SAP_MLME]) || (!hip_sap_cont.sap[SAP_MA]) || - (!hip_sap_cont.sap[SAP_DBG]) || (!hip_sap_cont.sap[SAP_TST])) - return NOTIFY_BAD; - - /* Check whether any sap is interested in the notifications */ - for (i = 0; i < SAP_TOTAL; i++) - if (hip_sap_cont.sap[i]->sap_notifier) { - if (hip_sap_cont.sap[i]->sap_notifier(sdev, event)) - return NOTIFY_BAD; - } - - switch (event) { - case SCSC_WIFI_STOP: - SLSI_INFO(sdev, "Freeze HIP4\n"); - mutex_lock(&sdev->hip.hip_mutex); - hip4_freeze(&sdev->hip4_inst); - mutex_unlock(&sdev->hip.hip_mutex); - break; - - case SCSC_WIFI_FAILURE_RESET: - SLSI_INFO(sdev, "Set HIP4 up again\n"); - mutex_lock(&sdev->hip.hip_mutex); - hip4_setup(&sdev->hip4_inst); - mutex_unlock(&sdev->hip.hip_mutex); - break; - - case SCSC_WIFI_SUSPEND: - SLSI_INFO(sdev, "Suspend HIP4\n"); - mutex_lock(&sdev->hip.hip_mutex); - hip4_suspend(&sdev->hip4_inst); - mutex_unlock(&sdev->hip.hip_mutex); - break; - - case SCSC_WIFI_RESUME: - SLSI_INFO(sdev, "Resume HIP4\n"); - mutex_lock(&sdev->hip.hip_mutex); - hip4_resume(&sdev->hip4_inst); - mutex_unlock(&sdev->hip.hip_mutex); - break; - - default: - SLSI_INFO(sdev, "Unknown event code %lu\n", event); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block cm_nb = { - .notifier_call = slsi_hip_service_notifier, -}; - -int slsi_hip_init(struct slsi_dev *sdev, struct device *dev) -{ - SLSI_UNUSED_PARAMETER(dev); - - memset(&sdev->hip4_inst, 0, sizeof(sdev->hip4_inst)); - - sdev->hip.sdev = sdev; - atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPED); - mutex_init(&sdev->hip.hip_mutex); - - /* Register with the service notifier to receiver - * asynchronus messages such as SCSC_WIFI_STOP(Freeze), SCSC_WIFI_FAILURE_RESET i - */ - slsi_wlan_service_notifier_register(&cm_nb); - - return 0; -} - -void slsi_hip_deinit(struct slsi_dev *sdev) -{ - slsi_wlan_service_notifier_unregister(&cm_nb); - mutex_destroy(&sdev->hip.hip_mutex); -} - -int slsi_hip_start(struct slsi_dev *sdev) -{ - if (!sdev->maxwell_core) { - SLSI_ERR(sdev, "Maxwell core does not exist\n"); - return -EINVAL; - } - - SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "[1/3]. Update HIP state (SLSI_HIP_STATE_STARTING)\n"); - atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STARTING); - - SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "[2/3]. Initialise HIP\n"); - if (hip4_init(&sdev->hip4_inst)) { - atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPED); - SLSI_ERR(sdev, "hip4_init failed\n"); - return -EINVAL; - } - - SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "[3/3]. Update HIP state (SLSI_HIP_STATE_STARTED)\n"); - atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STARTED); - - return 0; -} - -/* SAP rx proxy */ -int slsi_hip_rx(struct slsi_dev *sdev, struct sk_buff *skb) -{ - u16 pid; - - /* We enforce that all the SAPs are registered at this point */ - if ((!hip_sap_cont.sap[SAP_MLME]) || (!hip_sap_cont.sap[SAP_MA]) || - (!hip_sap_cont.sap[SAP_DBG]) || (!hip_sap_cont.sap[SAP_TST])) - return -ENODEV; - - /* Here we push a copy of the bare RECEIVED skb data also to the - * logring as a binary record. - * Note that bypassing UDI subsystem as a whole means we are losing: - * UDI filtering / UDI Header INFO / UDI QueuesFrames Throttling / - * UDI Skb Asynchronous processing - * We keep split DATA/CTRL path. - */ - if (fapi_is_ma(skb)) - SCSC_BIN_TAG_DEBUG(BIN_WIFI_DATA_RX, skb->data, skb->len); - else - SCSC_BIN_TAG_DEBUG(BIN_WIFI_CTRL_RX, skb->data, skb->len); - /* Udi test : If pid in UDI range then pass to UDI and ignore */ - slsi_log_clients_log_signal_fast(sdev, &sdev->log_clients, skb, SLSI_LOG_DIRECTION_TO_HOST); - pid = fapi_get_u16(skb, receiver_pid); - if (pid >= SLSI_TX_PROCESS_ID_UDI_MIN && pid <= SLSI_TX_PROCESS_ID_UDI_MAX) { - slsi_kfree_skb(skb); - return 0; - } - - if (fapi_is_ma(skb)) - return hip_sap_cont.sap[SAP_MA]->sap_handler(sdev, skb); - - if (fapi_is_mlme(skb)) - return hip_sap_cont.sap[SAP_MLME]->sap_handler(sdev, skb); - - if (fapi_is_debug(skb)) - return hip_sap_cont.sap[SAP_DBG]->sap_handler(sdev, skb); - - if (fapi_is_test(skb)) - return hip_sap_cont.sap[SAP_TST]->sap_handler(sdev, skb); - - return -EIO; -} - -/* Only DATA plane will look at the returning FB to account BoT */ -int slsi_hip_tx_done(struct slsi_dev *sdev, u16 colour) -{ - return hip_sap_cont.sap[SAP_MA]->sap_txdone(sdev, colour); -} - -int slsi_hip_setup(struct slsi_dev *sdev) -{ - /* Setup hip4 after initialization */ - return hip4_setup(&sdev->hip4_inst); -} - -#ifdef CONFIG_SCSC_SMAPPER -int slsi_hip_consume_smapper_entry(struct slsi_dev *sdev, struct sk_buff *skb) -{ - return hip4_smapper_consume_entry(sdev, &sdev->hip4_inst, skb); -} - -struct sk_buff *slsi_hip_get_skb_from_smapper(struct slsi_dev *sdev, struct sk_buff *skb) -{ - return hip4_smapper_get_skb(sdev, &sdev->hip4_inst, skb); -} - -void *slsi_hip_get_skb_data_from_smapper(struct slsi_dev *sdev, struct sk_buff *skb) -{ - return hip4_smapper_get_skb_data(sdev, &sdev->hip4_inst, skb); -} -#endif - -int slsi_hip_stop(struct slsi_dev *sdev) -{ - mutex_lock(&sdev->hip.hip_mutex); - SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "Update HIP state (SLSI_HIP_STATE_STOPPING)\n"); - atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPING); - - hip4_deinit(&sdev->hip4_inst); - - SLSI_DBG4(sdev, SLSI_HIP_INIT_DEINIT, "Update HIP state (SLSI_HIP_STATE_STOPPED)\n"); - atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_STOPPED); - - mutex_unlock(&sdev->hip.hip_mutex); - return 0; -} diff --git a/drivers/net/wireless/scsc/hip.h b/drivers/net/wireless/scsc/hip.h deleted file mode 100644 index b8dc04a91bbd..000000000000 --- a/drivers/net/wireless/scsc/hip.h +++ /dev/null @@ -1,79 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_HIP_H__ -#define __SLSI_HIP_H__ - -#include -#include -#include - -struct slsi_dev; - -/* This structure describes the chip and HIP core lib - * information that exposed to the OS layer. - */ -struct slsi_card_info { - u16 chip_id; - u32 fw_build; - u16 fw_hip_version; - u32 sdio_block_size; -}; - -/* HIP States: - * STOPPED : (default) state, avoid running the HIP - * STARTING : HIP is being initialised, avoid running the HIP - * STARTED : HIP cycles can run - * STOPPING : HIP is being de-initialised, avoid running the HIP - * BLOCKED : HIP TX CMD53 failure or WLAN subsystem crashed indication from Hydra, - * avoid running the HIP - */ -enum slsi_hip_state { - SLSI_HIP_STATE_STOPPED, - SLSI_HIP_STATE_STARTING, - SLSI_HIP_STATE_STARTED, - SLSI_HIP_STATE_STOPPING, - SLSI_HIP_STATE_BLOCKED -}; - -struct slsi_hip { - struct slsi_dev *sdev; - struct slsi_card_info card_info; - /* a std mutex */ - struct mutex hip_mutex; - - /* refer to enum slsi_hip_state */ - atomic_t hip_state; -}; - -#define SLSI_HIP_PARAM_SLOT_COUNT 2 - -int slsi_hip_init(struct slsi_dev *sdev, struct device *dev); -void slsi_hip_deinit(struct slsi_dev *sdev); - -int slsi_hip_start(struct slsi_dev *sdev); -int slsi_hip_setup(struct slsi_dev *sdev); -int slsi_hip_consume_smapper_entry(struct slsi_dev *sdev, struct sk_buff *skb); -void *slsi_hip_get_skb_data_from_smapper(struct slsi_dev *sdev, struct sk_buff *skb); -struct sk_buff *slsi_hip_get_skb_from_smapper(struct slsi_dev *sdev, struct sk_buff *skb); -int slsi_hip_stop(struct slsi_dev *sdev); - -/* Forward declaration */ -struct sap_api; -struct sk_buff; - -/* Register SAP with HIP layer */ -int slsi_hip_sap_register(struct sap_api *sap_api); -/* Unregister SAP with HIP layer */ -int slsi_hip_sap_unregister(struct sap_api *sap_api); -/* SAP rx proxy */ -int slsi_hip_rx(struct slsi_dev *sdev, struct sk_buff *skb); -/* SAP setup once we receive SAP versions */ -int slsi_hip_sap_setup(struct slsi_dev *sdev); -/* Allow the SAP to act on a buffer in the free list. */ -int slsi_hip_tx_done(struct slsi_dev *sdev, u16 colour); - -#endif diff --git a/drivers/net/wireless/scsc/hip4.c b/drivers/net/wireless/scsc/hip4.c deleted file mode 100644 index 554f6d1ba97d..000000000000 --- a/drivers/net/wireless/scsc/hip4.c +++ /dev/null @@ -1,2889 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_SCSC_WLAN_RX_NAPI -#include -#include -#endif - -#include "hip4.h" -#include "mbulk.h" -#include "dev.h" -#include "hip4_sampler.h" - -#ifdef CONFIG_ANDROID -#include "scsc_wifilogger_rings.h" -#endif - -#include "debug.h" - -static bool hip4_system_wq; -module_param(hip4_system_wq, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_system_wq, "Use system wq instead of named workqueue. (default: N)"); - -#ifdef CONFIG_SCSC_LOGRING -static bool hip4_dynamic_logging = true; -module_param(hip4_dynamic_logging, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_dynamic_logging, "Dynamic logging, logring is disabled if tput > hip4_qos_med_tput_in_mbps. (default: Y)"); - -static int hip4_dynamic_logging_tput_in_mbps = 150; -module_param(hip4_dynamic_logging_tput_in_mbps, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_dynamic_logging_tput_in_mbps, "throughput (in Mbps) to apply dynamic logring logging"); -#endif - -#ifdef CONFIG_SCSC_QOS -static bool hip4_qos_enable = true; -module_param(hip4_qos_enable, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_qos_enable, "enable HIP4 PM QoS. (default: Y)"); - -static int hip4_qos_max_tput_in_mbps = 300; -module_param(hip4_qos_max_tput_in_mbps, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_qos_max_tput_in_mbps, "throughput (in Mbps) to apply Max PM QoS"); - -static int hip4_qos_med_tput_in_mbps = 150; -module_param(hip4_qos_med_tput_in_mbps, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_qos_med_tput_in_mbps, "throughput (in Mbps) to apply Median PM QoS"); -#endif - -#ifdef CONFIG_SCSC_SMAPPER -static bool hip4_smapper_enable; -module_param(hip4_smapper_enable, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_smapper_enable, "enable HIP4 SMAPPER. (default: Y)"); -static bool hip4_smapper_is_enabled; -#endif - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI -/* run NAPI poll on a specific CPU (preferably a big CPU if online) */ -static int napi_select_cpu; /* CPU number */ -module_param(napi_select_cpu, int, 0644); -MODULE_PARM_DESC(napi_select_cpu, "select a specific CPU to execute NAPI poll"); -#endif - -static int max_buffered_frames = 10000; -module_param(max_buffered_frames, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(max_buffered_frames, "Maximum number of frames to buffer in the driver"); - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI -static ktime_t intr_received_fb; -static ktime_t bh_init_fb; -static ktime_t bh_end_fb; -static ktime_t intr_received_ctrl; -static ktime_t bh_init_ctrl; -static ktime_t bh_end_ctrl; -static ktime_t intr_received_data; -static ktime_t bh_init_data; -static ktime_t bh_end_data; -#endif -static ktime_t intr_received; -static ktime_t bh_init; -static ktime_t bh_end; - -static ktime_t wdt; -static ktime_t send; -static ktime_t closing; - -enum rw { - widx, - ridx, -}; - -static u8 hip4_read_index(struct slsi_hip4 *hip, u32 q, enum rw r_w); - -/* Q mapping V3 - V4 */ -/*offset of F/W owned indices */ -#define FW_OWN_OFS (64) -/** - * HIP queue indices layout in the scoreboard (SC-505612-DD). v3 - * - * 3 2 1 0 - * +-----------------------------------+ - * +0 | Q3R | Q2R | Q1W | Q0W | Owned by the host - * +-----------------------------------+ - * +4 | | | Q5W | Q4R | Owned by the host - * +-----------------------------------+ - * - * +-----------------------------------+ - * +64 | Q3W | Q2W | Q1R | Q0R | Owned by the F/W - * +-----------------------------------+ - * +68 | | | Q5R | Q4W | Owned by the F/W - * +-----------------------------------+ - * - * The queue indcies which owned by the host are only writable by the host. - * F/W can only read them. And vice versa. - */ -static int q_idx_layout[6][2] = { - { 0, FW_OWN_OFS + 0}, /* mif_q_fh_ctl : 0 */ - { 1, FW_OWN_OFS + 1}, /* mif_q_fh_dat : 1 */ - { FW_OWN_OFS + 2, 2}, /* mif_q_fh_rfb : 2 */ - { FW_OWN_OFS + 3, 3}, /* mif_q_th_ctl : 3 */ - { FW_OWN_OFS + 4, 4}, /* mif_q_th_dat : 4 */ - { 5, FW_OWN_OFS + 5} /* mif_q_th_rfb : 5 */ -}; - -/*offset of F/W owned VIF Status */ -#define FW_OWN_VIF (96) -/** - * HIP Pause state VIF. v4. 2 bits per PEER - * - * +-----------------------------------+ - * +96 | VIF[0] Peers [15-1] | Owned by the F/W - * +-----------------------------------+ - * +100 | VIF[0] Peers [31-16] | Owned by the F/W - * +-----------------------------------+ - * +104 | VIF[1] Peers [15-1] | Owned by the F/W - * +-----------------------------------+ - * +108 | VIF[1] Peers [31-16] | Owned by the F/W - * +-----------------------------------+ - * +112 | VIF[2] Peers [15-1] | Owned by the F/W - * +-----------------------------------+ - * +116 | VIF[2] Peers [31-16] | Owned by the F/W - * +-----------------------------------+ - * +120 | VIF[3] Peers [15-1] | Owned by the F/W - * +-----------------------------------+ - * +124 | VIF[3] Peers [31-16] | Owned by the F/W - * +-----------------------------------+ - * - */ - -/* MAX_STORM. Max Interrupts allowed when platform is in suspend */ -#define MAX_STORM 5 - -/* Timeout for Wakelocks in HIP */ -#define SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS (1000) - -#ifdef CONFIG_SCSC_WLAN_DEBUG - -static u64 histogram_1; -static u64 histogram_2; -static u64 histogram_3; -static u64 histogram_4; -static u64 histogram_5; -static u64 histogram_6; -static u64 max_jitter; - -#define HISTO_1 1000 /* 1 us */ -#define HISTO_2 10000 /* 10 us */ -#define HISTO_3 100000 /* 100 us */ -#define HISTO_4 1000000 /* 1ms */ -#define HISTO_5 10000000 /* 10ms */ - -static u64 histogram_1_data; -static u64 histogram_2_data; -static u64 histogram_3_data; -static u64 histogram_4_data; -static u64 histogram_5_data; -static u64 histogram_6_data; -static u64 max_data; - -#define HISTO_1_DATA 50 /* 50 th data packets */ -#define HISTO_2_DATA 100/* 100 th data packets */ -#define HISTO_3_DATA 150/* 150 th data packets */ -#define HISTO_4_DATA 200/* 200 th data packets */ -#define HISTO_5_DATA 250/* 250 th data packets */ - -/* MAX_HISTORY_RECORDS should be power of two */ -#define MAX_HISTORY_RECORDS 32 - -#define FH 0 -#define TH 1 - -struct hip4_history { - bool dir; - u32 signal; - u32 cnt; - ktime_t last_time; -} hip4_signal_history[MAX_HISTORY_RECORDS]; - -static u32 history_record; - -/* This function should be called from atomic context */ -static void hip4_history_record_add(bool dir, u32 signal_id) -{ - struct hip4_history record; - - record = hip4_signal_history[history_record]; - - if (record.signal == signal_id && record.dir == dir) { - /* If last signal and direction is the same, increment counter */ - record.last_time = ktime_get(); - record.cnt += 1; - hip4_signal_history[history_record] = record; - return; - } - - history_record = (history_record + 1) & (MAX_HISTORY_RECORDS - 1); - - record = hip4_signal_history[history_record]; - record.dir = dir; - record.signal = signal_id; - record.cnt = 1; - record.last_time = ktime_get(); - hip4_signal_history[history_record] = record; -} - -#define HIP4_HISTORY(in_seq_file, m, fmt, arg ...) \ - do { \ - if (in_seq_file) \ - seq_printf(m, fmt, ## arg); \ - else \ - SLSI_ERR_NODEV(fmt, ## arg); \ - } while (0) - -static void hip4_history_record_print(bool in_seq_file, struct seq_file *m) -{ - struct hip4_history record; - u32 i, pos; - ktime_t old; - - old = ktime_set(0, 0); - - /* Start with the Next record to print history in order */ - pos = (history_record + 1) & (MAX_HISTORY_RECORDS - 1); - - HIP4_HISTORY(in_seq_file, m, "dir\t signal\t cnt\t last_time(ns) \t\t gap(ns)\n"); - HIP4_HISTORY(in_seq_file, m, "-----------------------------------------------------------------------------\n"); - for (i = 0; i < MAX_HISTORY_RECORDS; i++) { - record = hip4_signal_history[pos]; - /*next pos*/ - if (record.cnt) { - HIP4_HISTORY(in_seq_file, m, "%s\t 0x%04x\t %d\t %lld \t%lld\n", record.dir ? "<--TH" : "FH-->", - record.signal, record.cnt, ktime_to_ns(record.last_time), ktime_to_ns(ktime_sub(record.last_time, old))); - } - old = record.last_time; - pos = (pos + 1) & (MAX_HISTORY_RECORDS - 1); - } -} - -static int hip4_proc_show_history(struct seq_file *m, void *v) -{ - hip4_history_record_print(true, m); - return 0; -} - -static int hip4_proc_history_open(struct inode *inode, struct file *file) -{ - return single_open(file, hip4_proc_show_history, PDE_DATA(inode)); -} - -static const struct file_operations hip4_procfs_history_fops = { - .owner = THIS_MODULE, - .open = hip4_proc_history_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int hip4_proc_show(struct seq_file *m, void *v) -{ - struct slsi_hip4 *hip = m->private; - struct hip4_hip_control *hip_control; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - u8 i; - - u32 conf_hip4_ver = 0; - void *hip_ptr; - - if (!hip->hip_priv) { - seq_puts(m, "HIP4 not active\n"); - return 0; - } - - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - /* Check if the version is supported. And get the index */ - /* This is hardcoded and may change in future versions */ - if (conf_hip4_ver != 4 && conf_hip4_ver != 3) { - SLSI_ERR_NODEV("FW Version %d not supported or Hip has not been set up\n", conf_hip4_ver); - return 0; - } - - /* hip_ref contains the reference of the start of shared memory allocated for WLAN */ - /* hip_ptr is the kernel address of hip_ref*/ - hip_ptr = scsc_mx_service_mif_addr_to_ptr(sdev->service, hip->hip_ref); - /* Get hip_control pointer on shared memory */ - hip_control = (struct hip4_hip_control *)(hip_ptr + - HIP4_WLAN_CONFIG_OFFSET); - - seq_puts(m, "-----------------------------------------\n"); - seq_puts(m, "HIP4 CONFIG:\n"); - seq_puts(m, "-----------------------------------------\n"); - seq_printf(m, "config kernel addr = %p\n", hip_control); - if (conf_hip4_ver == 4) { - seq_printf(m, "hip4_version_4 addr = 0x%p\n", &hip_control->config_v4); - seq_printf(m, "magic_number = 0x%x\n", hip_control->config_v4.magic_number); - seq_printf(m, "hip_config_ver = 0x%x\n", hip_control->config_v4.hip_config_ver); - seq_printf(m, "config_len = 0x%x\n", hip_control->config_v4.config_len); - seq_printf(m, "compat_flag = 0x%x\n", hip_control->config_v4.compat_flag); - seq_printf(m, "sap_mlme_ver = 0x%x\n", hip_control->config_v4.sap_mlme_ver); - seq_printf(m, "sap_ma_ver = 0x%x\n", hip_control->config_v4.sap_ma_ver); - seq_printf(m, "sap_debug_ver = 0x%x\n", hip_control->config_v4.sap_debug_ver); - seq_printf(m, "sap_test_ver = 0x%x\n", hip_control->config_v4.sap_test_ver); - seq_printf(m, "fw_build_id = 0x%x\n", hip_control->config_v4.fw_build_id); - seq_printf(m, "fw_patch_id = 0x%x\n", hip_control->config_v4.fw_patch_id); - seq_printf(m, "unidat_req_headroom = 0x%x\n", hip_control->config_v4.unidat_req_headroom); - seq_printf(m, "unidat_req_tailroom = 0x%x\n", hip_control->config_v4.unidat_req_tailroom); - seq_printf(m, "bulk_buffer_align = 0x%x\n", hip_control->config_v4.bulk_buffer_align); - seq_printf(m, "host_cache_line = 0x%x\n", hip_control->config_v4.host_cache_line); - seq_printf(m, "host_buf_loc = 0x%x\n", hip_control->config_v4.host_buf_loc); - seq_printf(m, "host_buf_sz = 0x%x\n", hip_control->config_v4.host_buf_sz); - seq_printf(m, "fw_buf_loc = 0x%x\n", hip_control->config_v4.fw_buf_loc); - seq_printf(m, "fw_buf_sz = 0x%x\n", hip_control->config_v4.fw_buf_sz); - seq_printf(m, "mib_buf_loc = 0x%x\n", hip_control->config_v4.mib_loc); - seq_printf(m, "mib_buf_sz = 0x%x\n", hip_control->config_v4.mib_sz); - seq_printf(m, "log_config_loc = 0x%x\n", hip_control->config_v4.log_config_loc); - seq_printf(m, "log_config_sz = 0x%x\n", hip_control->config_v4.log_config_sz); - seq_printf(m, "mif_fh_int_n = 0x%x\n", hip_control->config_v4.mif_fh_int_n); - seq_printf(m, "mif_th_int_n[FH_CTRL] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_FH_CTRL]); - seq_printf(m, "mif_th_int_n[FH_DAT] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_FH_DAT]); - seq_printf(m, "mif_th_int_n[FH_RFB] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_FH_RFB]); - seq_printf(m, "mif_th_int_n[TH_CTRL] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_TH_CTRL]); - seq_printf(m, "mif_th_int_n[TH_DAT] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_TH_DAT]); - seq_printf(m, "mif_th_int_n[TH_RFB] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_TH_RFB]); - seq_printf(m, "scbrd_loc = 0x%x\n", hip_control->config_v4.scbrd_loc); - seq_printf(m, "q_num = 0x%x\n", hip_control->config_v4.q_num); - seq_printf(m, "q_len = 0x%x\n", hip_control->config_v4.q_len); - seq_printf(m, "q_idx_sz = 0x%x\n", hip_control->config_v4.q_idx_sz); - for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) - seq_printf(m, "q_loc[%d] = 0x%x\n", i, hip_control->config_v4.q_loc[i]); - } else if (conf_hip4_ver == 5) { - seq_printf(m, "hip4_version_5 addr = 0x%p\n", &hip_control->config_v5); - seq_printf(m, "magic_number = 0x%x\n", hip_control->config_v5.magic_number); - seq_printf(m, "hip_config_ver = 0x%x\n", hip_control->config_v5.hip_config_ver); - seq_printf(m, "config_len = 0x%x\n", hip_control->config_v5.config_len); - seq_printf(m, "compat_flag = 0x%x\n", hip_control->config_v5.compat_flag); - seq_printf(m, "sap_mlme_ver = 0x%x\n", hip_control->config_v5.sap_mlme_ver); - seq_printf(m, "sap_ma_ver = 0x%x\n", hip_control->config_v5.sap_ma_ver); - seq_printf(m, "sap_debug_ver = 0x%x\n", hip_control->config_v5.sap_debug_ver); - seq_printf(m, "sap_test_ver = 0x%x\n", hip_control->config_v5.sap_test_ver); - seq_printf(m, "fw_build_id = 0x%x\n", hip_control->config_v5.fw_build_id); - seq_printf(m, "fw_patch_id = 0x%x\n", hip_control->config_v5.fw_patch_id); - seq_printf(m, "unidat_req_headroom = 0x%x\n", hip_control->config_v5.unidat_req_headroom); - seq_printf(m, "unidat_req_tailroom = 0x%x\n", hip_control->config_v5.unidat_req_tailroom); - seq_printf(m, "bulk_buffer_align = 0x%x\n", hip_control->config_v5.bulk_buffer_align); - seq_printf(m, "host_cache_line = 0x%x\n", hip_control->config_v5.host_cache_line); - seq_printf(m, "host_buf_loc = 0x%x\n", hip_control->config_v5.host_buf_loc); - seq_printf(m, "host_buf_sz = 0x%x\n", hip_control->config_v5.host_buf_sz); - seq_printf(m, "fw_buf_loc = 0x%x\n", hip_control->config_v5.fw_buf_loc); - seq_printf(m, "fw_buf_sz = 0x%x\n", hip_control->config_v5.fw_buf_sz); - seq_printf(m, "mib_buf_loc = 0x%x\n", hip_control->config_v5.mib_loc); - seq_printf(m, "mib_buf_sz = 0x%x\n", hip_control->config_v5.mib_sz); - seq_printf(m, "log_config_loc = 0x%x\n", hip_control->config_v5.log_config_loc); - seq_printf(m, "log_config_sz = 0x%x\n", hip_control->config_v5.log_config_sz); - seq_printf(m, "mif_fh_int_n = 0x%x\n", hip_control->config_v5.mif_fh_int_n); - seq_printf(m, "mif_th_int_n = 0x%x\n", hip_control->config_v5.mif_th_int_n); - seq_printf(m, "scbrd_loc = 0x%x\n", hip_control->config_v5.scbrd_loc); - seq_printf(m, "q_num = 0x%x\n", hip_control->config_v5.q_num); - seq_printf(m, "q_len = 0x%x\n", hip_control->config_v5.q_len); - seq_printf(m, "q_idx_sz = 0x%x\n", hip_control->config_v5.q_idx_sz); - for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) - seq_printf(m, "q_loc[%d] = 0x%x\n", i, hip_control->config_v5.q_loc[i]); - } - seq_puts(m, "\n-----------------------------------------\n"); - seq_puts(m, "HIP4 SCOREBOARD INDEXES:\n"); - seq_puts(m, "-----------------------------------------\n"); - seq_printf(m, "ktime start %lld (ns)\n", ktime_to_ns(hip->hip_priv->stats.start)); - seq_printf(m, "ktime now %lld (ns)\n\n", ktime_to_ns(ktime_get())); - - seq_printf(m, "rx_intr_tohost 0x%x\n", hip->hip_priv->intr_tohost); - seq_printf(m, "rx_intr_fromhost 0x%x\n\n", hip->hip_priv->intr_fromhost); - - /* HIP statistics */ - seq_printf(m, "HIP IRQs: %u\n", atomic_read(&hip->hip_priv->stats.irqs)); - seq_printf(m, "HIP IRQs spurious: %u\n", atomic_read(&hip->hip_priv->stats.spurious_irqs)); - seq_printf(m, "FW debug-inds: %u\n\n", atomic_read(&sdev->debug_inds)); - - seq_puts(m, "Queue\tIndex\tFrames\n"); - seq_puts(m, "-----\t-----\t------\n"); - /* Print scoreboard */ - for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) { - seq_printf(m, "Q%dW\t0x%x\t\n", i, hip4_read_index(hip, i, widx)); - seq_printf(m, "Q%dR\t0x%x\t%d\n", i, hip4_read_index(hip, i, ridx), hip->hip_priv->stats.q_num_frames[i]); - } - seq_puts(m, "\n"); - return 0; -} - -static int hip4_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, hip4_proc_show, PDE_DATA(inode)); -} - -static const struct file_operations hip4_procfs_stats_fops = { - .owner = THIS_MODULE, - .open = hip4_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int hip4_proc_jitter_show(struct seq_file *m, void *v) -{ - seq_puts(m, "Values in ns\n"); - seq_printf(m, "<%d(ns)\t\t\t\t %lld\n", HISTO_1, histogram_1); - seq_printf(m, "%d(ns)-%d(ns)\t\t\t %lld\n", HISTO_1, HISTO_2, histogram_2); - seq_printf(m, "%d(ns)-%d(ns)\t\t\t %lld\n", HISTO_2, HISTO_3, histogram_3); - seq_printf(m, "%d(ns)-%d(ns)\t\t\t %lld\n", HISTO_3, HISTO_4, histogram_4); - seq_printf(m, "%d(ns)-%d(ns)\t\t %lld\n", HISTO_4, HISTO_5, histogram_5); - seq_printf(m, ">%d(ns)\t\t\t\t %lld\n", HISTO_5, histogram_6); - seq_printf(m, "max jitter(ns)\t\t\t\t %lld\n", max_jitter); - seq_puts(m, "--------------------------\n"); - seq_puts(m, "Packets in TH DATA Q\n"); - seq_printf(m, "<%d\t\t%lld\n", HISTO_1_DATA, histogram_1_data); - seq_printf(m, "%d-%d\t\t%lld\n", HISTO_1_DATA, HISTO_2_DATA, histogram_2_data); - seq_printf(m, "%d-%d\t\t%lld\n", HISTO_2_DATA, HISTO_3_DATA, histogram_3_data); - seq_printf(m, "%d-%d\t\t%lld\n", HISTO_3_DATA, HISTO_4_DATA, histogram_4_data); - seq_printf(m, "%d-%d\t\t%lld\n", HISTO_4_DATA, HISTO_5_DATA, histogram_5_data); - seq_printf(m, ">%d\t\t%lld\n", HISTO_5_DATA, histogram_6_data); - seq_printf(m, "max data\t%lld\n", max_data); - return 0; -} - -static int hip4_proc_jitter_open(struct inode *inode, struct file *file) -{ - return single_open(file, hip4_proc_jitter_show, PDE_DATA(inode)); -} - -static ssize_t hip4_proc_jitter_clear(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - SLSI_INFO_NODEV("Clear Histogram\n"); - - histogram_1 = 0; - histogram_2 = 0; - histogram_3 = 0; - histogram_4 = 0; - histogram_5 = 0; - histogram_6 = 0; - max_jitter = 0; - - histogram_1_data = 0; - histogram_2_data = 0; - histogram_3_data = 0; - histogram_4_data = 0; - histogram_5_data = 0; - histogram_6_data = 0; - max_data = 0; - - return count; -} - -static const struct file_operations hip4_procfs_jitter_fops = { - .owner = THIS_MODULE, - .open = hip4_proc_jitter_open, - .write = hip4_proc_jitter_clear, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)) -static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec) -{ - return ktime_add_ns(kt, msec * NSEC_PER_MSEC); -} -#endif - -#define FB_NO_SPC_NUM_RET 100 -#define FB_NO_SPC_SLEEP_MS 10 -#define FB_NO_SPC_DELAY_US 1000 - -/* Update scoreboard index */ -/* Function can be called from BH context */ -static void hip4_update_index(struct slsi_hip4 *hip, u32 q, enum rw r_w, u8 value) -{ - struct hip4_priv *hip_priv = hip->hip_priv; - - write_lock_bh(&hip_priv->rw_scoreboard); - if (hip->hip_priv->version == 5 || hip->hip_priv->version == 4) { - *((u8 *)(hip->hip_priv->scbrd_base + q_idx_layout[q][r_w])) = value; - } else { - SLSI_ERR_NODEV("Incorrect version\n"); - goto error; - } - - /* Memory barrier when updating shared mailbox/memory */ - smp_wmb(); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, q, r_w, value, 0); -error: - write_unlock_bh(&hip_priv->rw_scoreboard); -} - -/* Read scoreboard index */ -/* Function can be called from BH context */ -static u8 hip4_read_index(struct slsi_hip4 *hip, u32 q, enum rw r_w) -{ - struct hip4_priv *hip_priv = hip->hip_priv; - u32 value = 0; - - read_lock_bh(&hip_priv->rw_scoreboard); - if (hip->hip_priv->version == 5 || hip->hip_priv->version == 4) { - value = *((u8 *)(hip->hip_priv->scbrd_base + q_idx_layout[q][r_w])); - } else { - SLSI_ERR_NODEV("Incorrect version\n"); - goto error; - } - - /* Memory barrier when reading shared mailbox/memory */ - smp_rmb(); -error: - read_unlock_bh(&hip_priv->rw_scoreboard); - return value; -} - -static void hip4_dump_dbg(struct slsi_hip4 *hip, struct mbulk *m, struct sk_buff *skb, struct scsc_service *service) -{ - unsigned int i = 0; - scsc_mifram_ref ref; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; - - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - - if (conf_hip4_ver == 4) { - SLSI_ERR_NODEV("intr_tohost_fb 0x%x\n", hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]); - SLSI_ERR_NODEV("intr_tohost_ctrl 0x%x\n", hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]); - SLSI_ERR_NODEV("intr_tohost_dat 0x%x\n", hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]); - } else { - SLSI_ERR_NODEV("intr_tohost 0x%x\n", hip->hip_priv->intr_tohost); - } -#else - SLSI_ERR_NODEV("intr_tohost 0x%x\n", hip->hip_priv->intr_tohost); -#endif - SLSI_ERR_NODEV("intr_fromhost 0x%x\n", hip->hip_priv->intr_fromhost); - - /* Print scoreboard */ - for (i = 0; i < 6; i++) { - SLSI_ERR_NODEV("Q%dW 0x%x\n", i, hip4_read_index(hip, i, widx)); - SLSI_ERR_NODEV("Q%dR 0x%x\n", i, hip4_read_index(hip, i, ridx)); - } - - if (service) - scsc_mx_service_mif_dump_registers(service); - - if (m && service) { - if (scsc_mx_service_mif_ptr_to_addr(service, m, &ref)) - return; - SLSI_ERR_NODEV("m: %p 0x%x\n", m, ref); - print_hex_dump(KERN_ERR, SCSC_PREFIX "mbulk ", DUMP_PREFIX_NONE, 16, 1, m, sizeof(struct mbulk), 0); - } - if (m && mbulk_has_signal(m)) - print_hex_dump(KERN_ERR, SCSC_PREFIX "sig ", DUMP_PREFIX_NONE, 16, 1, mbulk_get_signal(m), - MBULK_SEG_SIG_BUFSIZE(m), 0); - if (skb) - print_hex_dump(KERN_ERR, SCSC_PREFIX "skb ", DUMP_PREFIX_NONE, 16, 1, skb->data, skb->len > 0xff ? 0xff : skb->len, 0); - - SLSI_ERR_NODEV("time: wdt %lld\n", ktime_to_ns(wdt)); - SLSI_ERR_NODEV("time: send %lld\n", ktime_to_ns(send)); -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - if (conf_hip4_ver == 4) { - SLSI_ERR_NODEV("time: intr_fb %lld\n", ktime_to_ns(intr_received_fb)); - SLSI_ERR_NODEV("time: bh_init_fb %lld\n", ktime_to_ns(bh_init_fb)); - SLSI_ERR_NODEV("time: bh_end_fb %lld\n", ktime_to_ns(bh_end_fb)); - SLSI_ERR_NODEV("time: intr_ctrl %lld\n", ktime_to_ns(intr_received_ctrl)); - SLSI_ERR_NODEV("time: bh_init_ctrl %lld\n", ktime_to_ns(bh_init_ctrl)); - SLSI_ERR_NODEV("time: bh_end_ctrl %lld\n", ktime_to_ns(bh_end_ctrl)); - SLSI_ERR_NODEV("time: intr_data %lld\n", ktime_to_ns(intr_received_data)); - SLSI_ERR_NODEV("time: bh_init_data %lld\n", ktime_to_ns(bh_init_data)); - SLSI_ERR_NODEV("time: bh_end_data %lld\n", ktime_to_ns(bh_end_data)); - } else { - SLSI_ERR_NODEV("time: intr %lld\n", ktime_to_ns(intr_received)); - SLSI_ERR_NODEV("time: bh_init %lld\n", ktime_to_ns(bh_init)); - SLSI_ERR_NODEV("time: bh_end %lld\n", ktime_to_ns(bh_end)); - } -#else - SLSI_ERR_NODEV("time: intr %lld\n", ktime_to_ns(intr_received)); - SLSI_ERR_NODEV("time: bh_init %lld\n", ktime_to_ns(bh_init)); - SLSI_ERR_NODEV("time: bh_end %lld\n", ktime_to_ns(bh_end)); -#endif - SLSI_ERR_NODEV("time: closing %lld\n", ktime_to_ns(closing)); -#ifdef CONFIG_SCSC_WLAN_DEBUG - /* Discard noise if it is a mbulk/skb issue */ - if (!skb && !m) - hip4_history_record_print(false, NULL); -#endif -} - -/* Transform skb to mbulk (fapi_signal + payload) */ -static struct mbulk *hip4_skb_to_mbulk(struct hip4_priv *hip, struct sk_buff *skb, bool ctrl_packet) -{ - struct mbulk *m = NULL; - void *sig = NULL, *b_data = NULL; - size_t payload = 0; - u8 pool_id = ctrl_packet ? MBULK_POOL_ID_CTRL : MBULK_POOL_ID_DATA; - u8 headroom = 0, tailroom = 0; - enum mbulk_class clas = ctrl_packet ? MBULK_CLASS_FROM_HOST_CTL : MBULK_CLASS_FROM_HOST_DAT; - struct slsi_skb_cb *cb = slsi_skb_cb_get(skb); -#ifdef CONFIG_SCSC_WLAN_SG - u32 linear_data; - u32 offset; - u8 i; -#endif - - payload = skb->len - cb->sig_length; - - /* Get headroom/tailroom */ - headroom = hip->unidat_req_headroom; - tailroom = hip->unidat_req_tailroom; - - /* Allocate mbulk */ - if (payload > 0) { - /* If signal include payload, add headroom and tailroom */ - m = mbulk_with_signal_alloc_by_pool(pool_id, cb->colour, clas, cb->sig_length + 4, - payload + headroom + tailroom); - if (!m) - return NULL; - if (!mbulk_reserve_head(m, headroom)) - return NULL; - } else { - /* If it is only a signal do not add headroom */ - m = mbulk_with_signal_alloc_by_pool(pool_id, cb->colour, clas, cb->sig_length + 4, 0); - if (!m) - return NULL; - } - - /* Get signal handler */ - sig = mbulk_get_signal(m); - if (!sig) { - mbulk_free_virt_host(m); - return NULL; - } - - /* Copy signal */ - /* 4Bytes offset is required for FW fapi header */ - memcpy(sig + 4, skb->data, cb->sig_length); - - /* Copy payload */ - /* If the signal has payload memcpy the data */ - if (payload > 0) { - /* Get head pointer */ - b_data = mbulk_dat_rw(m); - if (!b_data) { - mbulk_free_virt_host(m); - return NULL; - } - -#ifdef CONFIG_SCSC_WLAN_SG - /* The amount of non-paged data at skb->data can be calculated as skb->len - skb->data_len. - * Helper routine: skb_headlen() . - */ - linear_data = skb_headlen(skb) - cb->sig_length; - - offset = 0; - /* Copy the linear data */ - if (linear_data > 0) { - /* Copy the linear payload skipping the signal data */ - memcpy(b_data, skb->data + cb->sig_length, linear_data); - offset = linear_data; - } - - /* Traverse fragments and copy in to linear DRAM memory */ - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - skb_frag_t *frag = NULL; - void *frag_va_data; - unsigned int frag_size; - - frag = &skb_shinfo(skb)->frags[i]; - WARN_ON(!frag); - if (!frag) - continue; - frag_va_data = skb_frag_address_safe(frag); - WARN_ON(!frag_va_data); - if (!frag_va_data) - continue; - frag_size = skb_frag_size(frag); - /* Copy the fragmented data */ - memcpy(b_data + offset, frag_va_data, frag_size); - offset += frag_size; - } - - /* Check whether the driver should perform the checksum */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { - SLSI_DBG3_NODEV(SLSI_HIP, "CHECKSUM_PARTIAL. Driver performing checksum\n"); - if (skb->protocol == htons(ETH_P_IP)) { - struct ethhdr *mach = (struct ethhdr *)b_data; - struct iphdr *iph = (struct iphdr *)((char *)b_data + sizeof(*mach)); - unsigned int len = payload - sizeof(*mach) - (iph->ihl << 2); - - if (iph->protocol == IPPROTO_TCP) { - struct tcphdr *th = (struct tcphdr *)((char *)b_data + sizeof(*mach) + - (iph->ihl << 2)); - th->check = 0; - th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, len, - IPPROTO_TCP, - csum_partial((char *)th, len, 0)); - SLSI_DBG3_NODEV(SLSI_HIP, "th->check 0x%x\n", ntohs(th->check)); - } else if (iph->protocol == IPPROTO_UDP) { - struct udphdr *uh = (struct udphdr *)((char *)b_data + sizeof(*mach) + - (iph->ihl << 2)); - uh->check = 0; - uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, len, - IPPROTO_UDP, - csum_partial((char *)uh, len, 0)); - SLSI_DBG3_NODEV(SLSI_HIP, "uh->check 0x%x\n", ntohs(uh->check)); - } - } - } -#else - /* Copy payload skipping the signal data */ - memcpy(b_data, skb->data + cb->sig_length, payload); -#endif - mbulk_append_tail(m, payload); - } - m->flag |= MBULK_F_OBOUND; - -#ifdef CONFIG_SCSC_SMAPPER - /* Clear smapper field */ - cb->skb_addr = NULL; -#endif - return m; -} - -/* Transform mbulk to skb (fapi_signal + payload) */ -static struct sk_buff *hip4_mbulk_to_skb(struct scsc_service *service, struct hip4_priv *hip_priv, struct mbulk *m, scsc_mifram_ref *to_free, bool atomic) -{ - struct slsi_skb_cb *cb; - struct mbulk *next_mbulk[MBULK_MAX_CHAIN]; - struct sk_buff *skb = NULL; - scsc_mifram_ref ref; - scsc_mifram_ref m_chain_next; - u8 free = 0; - u8 i = 0, j = 0; - u8 *p; - size_t bytes_to_alloc = 0; - - /* Get the mif ref pointer, check for incorrect mbulk */ - if (scsc_mx_service_mif_ptr_to_addr(service, m, &ref)) { - SLSI_ERR_NODEV("mbulk address conversion failed\n"); - return NULL; - } - - /* Track mbulk that should be freed */ - to_free[free++] = ref; - - bytes_to_alloc += m->sig_bufsz - 4; - bytes_to_alloc += m->len; - - /* Detect Chained mbulk to start building the chain */ - if ((MBULK_SEG_IS_CHAIN_HEAD(m)) && (MBULK_SEG_IS_CHAINED(m))) { - m_chain_next = mbulk_chain_next(m); - if (!m_chain_next) { - SLSI_ERR_NODEV("Mbulk is set MBULK_F_CHAIN_HEAD and MBULK_F_CHAIN but m_chain_next is NULL\n"); - goto cont; - } - while (1) { - /* increase number mbulks in chain */ - i++; - /* Get next_mbulk kernel address space pointer */ - next_mbulk[i - 1] = scsc_mx_service_mif_addr_to_ptr(service, m_chain_next); - if (!next_mbulk[i - 1]) { - SLSI_ERR_NODEV("First Mbulk is set as MBULK_F_CHAIN but next_mbulk is NULL\n"); - return NULL; - } - /* Track mbulk to be freed */ - to_free[free++] = m_chain_next; - bytes_to_alloc += next_mbulk[i - 1]->len; - if (MBULK_SEG_IS_CHAINED(next_mbulk[i - 1])) { - /* continue traversing the chain */ - m_chain_next = mbulk_chain_next(next_mbulk[i - 1]); - if (!m_chain_next) - break; - - if (i >= MBULK_MAX_CHAIN) { - SLSI_ERR_NODEV("Max number of chained MBULK reached\n"); - return NULL; - } - } else { - break; - } - } - } - -cont: - if (atomic) - skb = slsi_alloc_skb(bytes_to_alloc, GFP_ATOMIC); - else { - spin_unlock_bh(&hip_priv->rx_lock); - skb = slsi_alloc_skb(bytes_to_alloc, GFP_KERNEL); - spin_lock_bh(&hip_priv->rx_lock); - } - if (!skb) { - SLSI_ERR_NODEV("Error allocating skb %d bytes\n", bytes_to_alloc); - return NULL; - } - - cb = slsi_skb_cb_init(skb); - cb->sig_length = m->sig_bufsz - 4; - /* fapi_data_append adds to the data_length */ - cb->data_length = cb->sig_length; - - p = mbulk_get_signal(m); - if (!p) { - SLSI_ERR_NODEV("No signal in Mbulk\n"); - print_hex_dump(KERN_ERR, SCSC_PREFIX "mbulk ", DUMP_PREFIX_NONE, 16, 1, m, sizeof(struct mbulk), 0); - slsi_kfree_skb(skb); - return NULL; - } - /* Remove 4Bytes offset coming from FW */ - p += 4; - - /* Don't need to copy the 4Bytes header coming from the FW */ - memcpy(skb_put(skb, cb->sig_length), p, cb->sig_length); - - if (m->len) - fapi_append_data(skb, mbulk_dat_r(m), m->len); - for (j = 0; j < i; j++) - fapi_append_data(skb, mbulk_dat_r(next_mbulk[j]), next_mbulk[j]->len); - - return skb; -} - -/* Add signal reference (offset in shared memory) in the selected queue */ -/* This function should be called in atomic context. Callers should supply proper locking mechanism */ -static int hip4_q_add_signal(struct slsi_hip4 *hip, enum hip4_hip_q_conf conf, scsc_mifram_ref phy_m, struct scsc_service *service) -{ - struct hip4_hip_control *ctrl = hip->hip_control; - struct hip4_priv *hip_priv = hip->hip_priv; - u8 idx_w; - u8 idx_r; - - /* Read the current q write pointer */ - idx_w = hip4_read_index(hip, conf, widx); - /* Read the current q read pointer */ - idx_r = hip4_read_index(hip, conf, ridx); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, conf, widx, idx_w, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, conf, ridx, idx_r, 1); - - /* Queueu is full */ - if (idx_r == ((idx_w + 1) & (MAX_NUM - 1))) - return -ENOSPC; - - /* Update array */ - ctrl->q[conf].array[idx_w] = phy_m; - /* Memory barrier before updating shared mailbox */ - smp_wmb(); - SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, phy_m, conf); -#ifdef CONFIG_SCSC_WLAN_DEBUG - hip->hip_priv->stats.q_num_frames[conf] = hip->hip_priv->stats.q_num_frames[conf] + 1; -#endif - - /* Increase index */ - idx_w++; - idx_w &= (MAX_NUM - 1); - - /* Update the scoreboard */ - hip4_update_index(hip, conf, widx, idx_w); - - send = ktime_get(); - scsc_service_mifintrbit_bit_set(service, hip_priv->intr_fromhost, SCSC_MIFINTR_TARGET_R4); - - return 0; -} - -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE -static void hip4_watchdog(struct timer_list *t) -#else -static void hip4_watchdog(unsigned long data) -#endif -{ -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - struct hip4_priv *priv = from_timer(priv, t, watchdog); - struct slsi_hip4 *hip = priv->hip; -#else - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; -#endif - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - struct scsc_service *service; - ktime_t intr_ov; - unsigned long flags; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - bool retrigger_watchdog = true; - u32 conf_hip4_ver = 0; -#endif - - if (!hip || !sdev || !sdev->service || !hip->hip_priv) - return; - - spin_lock_irqsave(&hip->hip_priv->watchdog_lock, flags); - if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) - goto exit; - - wdt = ktime_get(); - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - - if (conf_hip4_ver == 4) { - /* if intr_received > wdt skip as intr has been unblocked */ - if (test_and_clear_bit(HIP4_MIF_Q_FH_RFB, hip->hip_priv->irq_bitmap)) { - intr_ov = ktime_add_ms(intr_received_fb, jiffies_to_msecs(HZ)); - if ((ktime_compare(intr_ov, wdt) < 0)) - retrigger_watchdog = false; - } - if (test_and_clear_bit(HIP4_MIF_Q_TH_CTRL, hip->hip_priv->irq_bitmap)) { - intr_ov = ktime_add_ms(intr_received_ctrl, jiffies_to_msecs(HZ)); - if ((ktime_compare(intr_ov, wdt) < 0)) - retrigger_watchdog = false; - } - if (test_and_clear_bit(HIP4_MIF_Q_TH_DAT, hip->hip_priv->irq_bitmap)) { - intr_ov = ktime_add_ms(intr_received_data, jiffies_to_msecs(HZ)); - if ((ktime_compare(intr_ov, wdt) < 0)) - retrigger_watchdog = false; - } - if (retrigger_watchdog) { - wdt = ktime_set(0, 0); - /* Retrigger WDT to check flags again in the future */ - mod_timer(&hip->hip_priv->watchdog, jiffies + HZ / 2); - goto exit; - } - } else { - /* if intr_received > wdt skip as intr has been unblocked */ - if (ktime_compare(intr_received, wdt) > 0) { - wdt = ktime_set(0, 0); - goto exit; - } - - intr_ov = ktime_add_ms(intr_received, jiffies_to_msecs(HZ)); - - /* Check that wdt is > 1 HZ intr */ - if (!(ktime_compare(intr_ov, wdt) < 0)) { - wdt = ktime_set(0, 0); - /* Retrigger WDT to check flags again in the future */ - mod_timer(&hip->hip_priv->watchdog, jiffies + HZ / 2); - goto exit; - } - } -#else - /* if intr_received > wdt skip as intr has been unblocked */ - if (ktime_compare(intr_received, wdt) > 0) { - wdt = ktime_set(0, 0); - goto exit; - } - - intr_ov = ktime_add_ms(intr_received, jiffies_to_msecs(HZ)); - - /* Check that wdt is > 1 HZ intr */ - if (!(ktime_compare(intr_ov, wdt) < 0)) { - wdt = ktime_set(0, 0); - /* Retrigger WDT to check flags again in the future */ - mod_timer(&hip->hip_priv->watchdog, jiffies + HZ / 2); - goto exit; - } -#endif - - /* Unlock irq to avoid __local_bh_enable_ip warning */ - spin_unlock_irqrestore(&hip->hip_priv->watchdog_lock, flags); - hip4_dump_dbg(hip, NULL, NULL, sdev->service); - spin_lock_irqsave(&hip->hip_priv->watchdog_lock, flags); - - service = sdev->service; - - SLSI_INFO_NODEV("Hip4 watchdog triggered\n"); - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - if (conf_hip4_ver == 4) { - for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++) { - if (hip->hip_priv->intr_tohost_mul[i] == MIF_NO_IRQ) - continue; - if (scsc_service_mifintrbit_bit_mask_status_get(service) & (1 << hip->hip_priv->intr_tohost_mul[i])) { - /* Interrupt might be pending! */ - SLSI_INFO_NODEV("%d: Interrupt Masked. Unmask to restart Interrupt processing\n", i); - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]); - } - } - } else { - if (scsc_service_mifintrbit_bit_mask_status_get(service) & (1 << hip->hip_priv->intr_tohost)) { - /* Interrupt might be pending! */ - SLSI_INFO_NODEV("Interrupt Masked. Unmask to restart Interrupt processing\n"); - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); - } - } -#else - if (scsc_service_mifintrbit_bit_mask_status_get(service) & (1 << hip->hip_priv->intr_tohost)) { - /* Interrupt might be pending! */ - SLSI_INFO_NODEV("Interrupt Masked. Unmask to restart Interrupt processing\n"); - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); - } -#endif -exit: - spin_unlock_irqrestore(&hip->hip_priv->watchdog_lock, flags); -} - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI -static void hip4_wq_fb(struct work_struct *data) -{ - struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, intr_wq_fb); - struct slsi_hip4 *hip; - struct hip4_hip_control *ctrl; - struct scsc_service *service; - struct slsi_dev *sdev; - bool no_change = true; - u8 idx_r; - u8 idx_w; - scsc_mifram_ref ref; - void *mem; - - if (!hip_priv || !hip_priv->hip) { - SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n"); - return; - } - - hip = hip_priv->hip; - ctrl = hip->hip_control; - - if (!ctrl) { - SLSI_ERR_NODEV("hip->hip_control is Null\n"); - return; - } - sdev = container_of(hip, struct slsi_dev, hip4_inst); - - if (!sdev || !sdev->service) { - SLSI_ERR_NODEV("sdev or sdev->service is Null\n"); - return; - } - - spin_lock_bh(&hip_priv->rx_lock); - service = sdev->service; - SCSC_HIP4_SAMPLER_INT_BH(hip->hip_priv->minor, 2); - bh_init_fb = ktime_get(); - clear_bit(HIP4_MIF_Q_FH_RFB, hip->hip_priv->irq_bitmap); - - idx_r = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, ridx); - idx_w = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, widx); - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - if (idx_r != idx_w) { - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, ridx, idx_r, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, widx, idx_w, 1); - } -#endif - while (idx_r != idx_w) { - struct mbulk *m; - u16 colour; - - no_change = false; - ref = ctrl->q[HIP4_MIF_Q_FH_RFB].array[idx_r]; -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_FH_RFB); -#endif - mem = scsc_mx_service_mif_addr_to_ptr(service, ref); - m = (struct mbulk *)mem; - - if (!m) { - SLSI_ERR_NODEV("FB: Mbulk is NULL\n"); - goto consume_fb_mbulk; - } - /* colour is defined as: */ - /* u16 register bits: - * 0 - do not use - * [2:1] - vif - * [7:3] - peer_index - * [10:8] - ac queue - */ - colour = ((m->clas & 0xc0) << 2) | (m->pid & 0xfe); - /* Account ONLY for data RFB */ - if ((m->pid & 0x1) == MBULK_POOL_ID_DATA) { -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0x6) >> 1, (colour & 0xf8) >> 3); - /* to profile round-trip */ - { - u16 host_tag; - u8 *get_host_tag; - /* This is a nasty way of getting the host_tag without involving mbulk processing - * This hostag value should also be include in the cb descriptor which goes to - * mbulk descriptor (no room left at the moment) - */ - get_host_tag = (u8 *)m; - host_tag = get_host_tag[37] << 8 | get_host_tag[36]; - SCSC_HIP4_SAMPLER_PKT_TX_FB(hip->hip_priv->minor, host_tag); - } -#endif - /* Ignore return value */ - slsi_hip_tx_done(sdev, colour); - } - mbulk_free_virt_host(m); -consume_fb_mbulk: - /* Increase index */ - idx_r++; - idx_r &= (MAX_NUM - 1); - hip4_update_index(hip, HIP4_MIF_Q_FH_RFB, ridx, idx_r); - } - - if (no_change) - atomic_inc(&hip->hip_priv->stats.spurious_irqs); - - if (!atomic_read(&hip->hip_priv->closing)) { - atomic_set(&hip->hip_priv->watchdog_timer_active, 0); - scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]); - } - SCSC_HIP4_SAMPLER_INT_OUT_BH(hip->hip_priv->minor, 2); - -#ifdef CONFIG_ANDROID - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock_tx); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_tx", WL_REASON_RX); - } -#endif - bh_end_fb = ktime_get(); - spin_unlock_bh(&hip_priv->rx_lock); -} - -static void hip4_irq_handler_fb(int irq, void *data) -{ - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - - SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 2); - intr_received_fb = ktime_get(); - -#ifdef CONFIG_ANDROID - if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) { - wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_tx, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS)); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_tx", WL_REASON_RX); - } -#endif - - if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) { - atomic_set(&hip->hip_priv->watchdog_timer_active, 1); - mod_timer(&hip->hip_priv->watchdog, jiffies + HZ); - } - set_bit(HIP4_MIF_Q_FH_RFB, hip->hip_priv->irq_bitmap); - - scsc_service_mifintrbit_bit_mask(sdev->service, irq); - if (hip4_system_wq) - schedule_work(&hip->hip_priv->intr_wq_fb); - else - queue_work(hip->hip_priv->hip4_workq, &hip->hip_priv->intr_wq_fb); - - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(sdev->service, irq); - SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 2); -} - -static void hip4_wq_ctrl(struct work_struct *data) -{ - struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, intr_wq_ctrl); - struct slsi_hip4 *hip; - struct hip4_hip_control *ctrl; - struct scsc_service *service; - struct slsi_dev *sdev; - u8 retry; - bool no_change = true; - u8 idx_r; - u8 idx_w; - scsc_mifram_ref ref; - void *mem; - struct mbulk *m; -#if defined(CONFIG_SCSC_WLAN_DEBUG) || defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) - int id; -#endif - - if (!hip_priv || !hip_priv->hip) { - SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n"); - return; - } - - hip = hip_priv->hip; - ctrl = hip->hip_control; - - if (!ctrl) { - SLSI_ERR_NODEV("hip->hip_control is Null\n"); - return; - } - sdev = container_of(hip, struct slsi_dev, hip4_inst); - - if (!sdev || !sdev->service) { - SLSI_ERR_NODEV("sdev or sdev->service is Null\n"); - return; - } - - spin_lock_bh(&hip_priv->rx_lock); - service = sdev->service; - SCSC_HIP4_SAMPLER_INT_BH(hip->hip_priv->minor, 1); - bh_init_ctrl = ktime_get(); - clear_bit(HIP4_MIF_Q_TH_CTRL, hip->hip_priv->irq_bitmap); - - idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, ridx); - idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, widx); - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - if (idx_r != idx_w) { - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, ridx, idx_r, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, widx, idx_w, 1); - } -#endif - while (idx_r != idx_w) { - struct sk_buff *skb; - /* TODO: currently the max number to be freed is 2. In future - * implementations (i.e. AMPDU) this number may be bigger - * list of mbulks to be freedi - */ - scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 }; - u8 i = 0; - - no_change = false; - /* Catch-up with idx_w */ - ref = ctrl->q[HIP4_MIF_Q_TH_CTRL].array[idx_r]; -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_CTRL); -#endif - mem = scsc_mx_service_mif_addr_to_ptr(service, ref); - m = (struct mbulk *)(mem); - /* Process Control Signal */ - skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, false); - if (!skb) { - SLSI_ERR_NODEV("Ctrl: Error parsing or allocating skb\n"); - hip4_dump_dbg(hip, m, skb, service); - goto consume_ctl_mbulk; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (m->flag & MBULK_F_WAKEUP) { - SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x:\n", fapi_get_sigid(skb)); - SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len); - } -#else - if (m->flag & MBULK_F_WAKEUP) - SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x\n", fapi_get_sigid(skb)); -#endif - -#if defined(CONFIG_SCSC_WLAN_DEBUG) || defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) - id = fapi_get_sigid(skb); -#endif -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - /* log control signal, not unidata not debug */ - if (fapi_is_mlme(skb)) - SCSC_HIP4_SAMPLER_SIGNAL_CTRLRX(hip_priv->minor, (id & 0xff00) >> 8, id & 0xff); -#endif -#ifdef CONFIG_SCSC_WLAN_DEBUG - hip4_history_record_add(TH, id); -#endif - if (slsi_hip_rx(sdev, skb) < 0) { - SLSI_ERR_NODEV("Ctrl: Error detected slsi_hip_rx\n"); - hip4_dump_dbg(hip, m, skb, service); - slsi_kfree_skb(skb); - } -consume_ctl_mbulk: - /* Increase index */ - idx_r++; - idx_r &= (MAX_NUM - 1); - - /* Go through the list of references to free */ - while ((ref = to_free[i++])) { - /* Set the number of retries */ - retry = FB_NO_SPC_NUM_RET; - /* return to the firmware */ - while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) { - SLSI_WARN_NODEV("Ctrl: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET); - spin_unlock_bh(&hip_priv->rx_lock); - msleep(FB_NO_SPC_SLEEP_MS); - spin_lock_bh(&hip_priv->rx_lock); - retry--; - if (retry == 0) - SLSI_ERR_NODEV("Ctrl: FB has not been freed for %d ms\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_SLEEP_MS); - SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB); - } - } - hip4_update_index(hip, HIP4_MIF_Q_TH_CTRL, ridx, idx_r); - } - - if (no_change) - atomic_inc(&hip->hip_priv->stats.spurious_irqs); - - if (!atomic_read(&hip->hip_priv->closing)) { - atomic_set(&hip->hip_priv->watchdog_timer_active, 0); - scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]); - } - SCSC_HIP4_SAMPLER_INT_OUT_BH(hip->hip_priv->minor, 1); -#ifdef CONFIG_ANDROID - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_ctrl)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock_ctrl); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_ctrl", WL_REASON_RX); - } -#endif - bh_end_ctrl = ktime_get(); - spin_unlock_bh(&hip_priv->rx_lock); -} - -static void hip4_irq_handler_ctrl(int irq, void *data) -{ - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - - SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 1); - intr_received_ctrl = ktime_get(); - -#ifdef CONFIG_ANDROID - if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_ctrl)) { - wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_ctrl, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS)); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_ctrl", WL_REASON_RX); - } -#endif - - if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) { - atomic_set(&hip->hip_priv->watchdog_timer_active, 1); - mod_timer(&hip->hip_priv->watchdog, jiffies + HZ); - } - set_bit(HIP4_MIF_Q_TH_CTRL, hip->hip_priv->irq_bitmap); - - scsc_service_mifintrbit_bit_mask(sdev->service, irq); - - if (hip4_system_wq) - schedule_work(&hip->hip_priv->intr_wq_ctrl); - else - queue_work(hip->hip_priv->hip4_workq, &hip->hip_priv->intr_wq_ctrl); - - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(sdev->service, irq); - SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 1); -} - -static int hip4_napi_poll(struct napi_struct *napi, int budget) -{ - struct hip4_priv *hip_priv = container_of(napi, struct hip4_priv, napi); - struct slsi_hip4 *hip; - struct hip4_hip_control *ctrl; - struct scsc_service *service; - struct slsi_dev *sdev; - -#ifdef CONFIG_SCSC_WLAN_DEBUG - int id; -#endif - u8 idx_r; - u8 idx_w; - scsc_mifram_ref ref; - void *mem; - struct mbulk *m; - u8 retry; - int work_done = 0; - - if (!hip_priv || !hip_priv->hip) { - SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n"); - return 0; - } - - hip = hip_priv->hip; - ctrl = hip->hip_control; - - if (!ctrl) { - SLSI_ERR_NODEV("hip->hip_control is Null\n"); - return 0; - } - sdev = container_of(hip, struct slsi_dev, hip4_inst); - - if (!sdev || !sdev->service) { - SLSI_ERR_NODEV("sdev or sdev->service is Null\n"); - return 0; - } - - spin_lock_bh(&hip_priv->rx_lock); - SCSC_HIP4_SAMPLER_INT_BH(hip->hip_priv->minor, 0); - if (ktime_compare(bh_init_data, bh_end_data) <= 0) { - bh_init_data = ktime_get(); - if (!atomic_read(&hip->hip_priv->closing)) { - atomic_set(&hip->hip_priv->watchdog_timer_active, 0); - } - } - clear_bit(HIP4_MIF_Q_TH_DAT, hip->hip_priv->irq_bitmap); - - idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, ridx); - idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, widx); - - service = sdev->service; - - SLSI_DBG4(sdev, SLSI_RX, "todo:%d\n", (idx_w - idx_r) & 0xff); - if (idx_r == idx_w) { - SLSI_DBG4(sdev, SLSI_RX, "nothing to do, NAPI Complete\n"); - bh_end_data = ktime_get(); - napi_complete(napi); - if (!atomic_read(&hip->hip_priv->closing)) { - /* Nothing more to drain, unmask interrupt */ - scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]); - } -#ifdef CONFIG_ANDROID - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_data)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock_data); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_data", WL_REASON_RX); - } -#endif - goto end; - } - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - if (idx_r != idx_w) { - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, ridx, idx_r, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, widx, idx_w, 1); - } -#endif - - while (idx_r != idx_w) { - struct sk_buff *skb; - /* TODO: currently the max number to be freed is 2. In future - * implementations (i.e. AMPDU) this number may be bigger - */ - /* list of mbulks to be freed */ - scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 }; - u8 i = 0; - - /* Catch-up with idx_w */ - ref = ctrl->q[HIP4_MIF_Q_TH_DAT].array[idx_r]; -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_DAT); -#endif - mem = scsc_mx_service_mif_addr_to_ptr(service, ref); - m = (struct mbulk *)(mem); - skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, true); - if (!skb) { - SLSI_ERR_NODEV("Dat: Error parsing or allocating skb\n"); - hip4_dump_dbg(hip, m, skb, service); - goto consume_dat_mbulk; - } -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (m->flag & MBULK_F_WAKEUP) { - SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n"); - SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len); - } -#else - if (m->flag & MBULK_F_WAKEUP) { - SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n"); - SCSC_BIN_TAG_INFO(BINARY, skb->data, fapi_get_siglen(skb) + ETH_HLEN); - } -#endif -#ifdef CONFIG_SCSC_WLAN_DEBUG - id = fapi_get_sigid(skb); - hip4_history_record_add(TH, id); -#endif - if (slsi_hip_rx(sdev, skb) < 0) { - SLSI_ERR_NODEV("Dat: Error detected slsi_hip_rx\n"); - hip4_dump_dbg(hip, m, skb, service); - slsi_kfree_skb(skb); - } -consume_dat_mbulk: - /* Increase index */ - idx_r++; - idx_r &= (MAX_NUM - 1); - - while ((ref = to_free[i++])) { - /* Set the number of retries */ - retry = FB_NO_SPC_NUM_RET; - while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) { - SLSI_WARN_NODEV("Dat: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET); - udelay(FB_NO_SPC_DELAY_US); - retry--; - - if (retry == 0) - SLSI_ERR_NODEV("Dat: FB has not been freed for %d us\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_DELAY_US); -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB); -#endif - } - } - - work_done++; - if (budget == work_done) { - /* We have consumed all the bugdet */ - break; - } - } - - hip4_update_index(hip, HIP4_MIF_Q_TH_DAT, ridx, idx_r); - - if (work_done < budget) { - SLSI_DBG4(sdev, SLSI_RX, "NAPI Complete\n"); - bh_end_data = ktime_get(); - napi_complete(napi); - if (!atomic_read(&hip->hip_priv->closing)) { - /* Nothing more to drain, unmask interrupt */ - scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]); - } -#ifdef CONFIG_ANDROID - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_data)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock_data); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_data", WL_REASON_RX); - } -#endif - } -end: - SLSI_DBG4(sdev, SLSI_RX, "work done:%d\n", work_done); - SCSC_HIP4_SAMPLER_INT_OUT_BH(hip->hip_priv->minor, 0); - spin_unlock_bh(&hip_priv->rx_lock); - return work_done; -} - -static void hip4_napi_schedule(void *data) -{ - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; - - napi_schedule(&hip->hip_priv->napi); -} - -static void hip4_irq_data_tasklet(unsigned long data) -{ - /* TODO: NAPI - formalize the CPU selection code */ - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; - int err = -EINVAL; - - if (cpu_online(napi_select_cpu)) - err = smp_call_function_single(napi_select_cpu, hip4_napi_schedule, hip, 0); - - if (err) - napi_schedule(&hip->hip_priv->napi); -} - -static void hip4_irq_handler_dat(int irq, void *data) -{ - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - - if (!hip || !sdev || !sdev->service || !hip->hip_priv) - return; - - SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 0); - intr_received_data = ktime_get(); - -#ifdef CONFIG_ANDROID - if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_data)) { - wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_data, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS)); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_data", WL_REASON_RX); - } -#endif - if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) { - atomic_set(&hip->hip_priv->watchdog_timer_active, 1); - mod_timer(&hip->hip_priv->watchdog, jiffies + HZ); - } - set_bit(HIP4_MIF_Q_TH_DAT, hip->hip_priv->irq_bitmap); - - if (napi_select_cpu) - tasklet_schedule(&hip->hip_priv->intr_tasklet); - else - napi_schedule(&hip->hip_priv->napi); - - /* Mask interrupt to avoid interrupt storm and let BH run */ - scsc_service_mifintrbit_bit_mask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]); - - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]); - SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 0); -} - -#endif /* #ifdef CONFIG_SCSC_WLAN_RX_NAPI */ - -static bool slsi_check_rx_flowcontrol(struct slsi_dev *sdev) -{ - struct netdev_vif *ndev_vif; - int qlen = 0; - - ndev_vif = netdev_priv(sdev->netdev[SLSI_NET_INDEX_WLAN]); - if (ndev_vif) - qlen = skb_queue_len(&ndev_vif->rx_data.queue); - - if (!mutex_trylock(&sdev->netdev_remove_mutex)) - goto evaluate; - -#if defined(SLSI_NET_INDEX_P2PX_SWLAN) - if (sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]) { - ndev_vif = netdev_priv(sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]); - if (ndev_vif) - qlen += skb_queue_len(&ndev_vif->rx_data.queue); - } -#elif defined(SLSI_NET_INDEX_P2PX) - if (sdev->netdev[SLSI_NET_INDEX_P2PX]) { - ndev_vif = netdev_priv(sdev->netdev[SLSI_NET_INDEX_P2PX]); - if (ndev_vif) - qlen += skb_queue_len(&ndev_vif->rx_data.queue); - } -#endif - mutex_unlock(&sdev->netdev_remove_mutex); - -evaluate: - if (qlen > max_buffered_frames) { - SLSI_DBG1_NODEV(SLSI_HIP, "max qlen reached: %d\n", qlen); - return true; - } - SLSI_DBG3_NODEV(SLSI_HIP, "qlen %d\n", qlen); - - return false; -} - -/* Worqueue: Lower priority, run in process context. Can run simultaneously on - * different CPUs - */ -static void hip4_wq(struct work_struct *data) -{ - struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, intr_wq); - struct slsi_hip4 *hip = hip_priv->hip; - struct hip4_hip_control *ctrl = hip->hip_control; - scsc_mifram_ref ref; - void *mem; - struct mbulk *m; - u8 idx_r; - u8 idx_w; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - struct scsc_service *service; - bool no_change = true; - u8 retry; - u32 packets_total; - bool rx_flowcontrol = false; - -#if defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) || defined(CONFIG_SCSC_WLAN_DEBUG) - int id; -#endif - - if (!sdev || !sdev->service) { - WARN_ON(1); - return; - } - - service = sdev->service; - - atomic_set(&hip->hip_priv->in_rx, 1); - if (slsi_check_rx_flowcontrol(sdev)) - rx_flowcontrol = true; - - atomic_set(&hip->hip_priv->in_rx, 2); - spin_lock_bh(&hip_priv->rx_lock); - atomic_set(&hip->hip_priv->in_rx, 3); - - bh_init = ktime_get(); - -#ifdef CONFIG_SCSC_WLAN_DEBUG - /* Compute jitter */ - { - u64 jitter; - - jitter = ktime_to_ns(ktime_sub(bh_init, intr_received)); - - if (jitter <= HISTO_1) - histogram_1++; - else if (jitter > HISTO_1 && jitter <= HISTO_2) - histogram_2++; - else if (jitter > HISTO_2 && jitter <= HISTO_3) - histogram_3++; - else if (jitter > HISTO_3 && jitter <= HISTO_4) - histogram_4++; - else if (jitter > HISTO_4 && jitter <= HISTO_5) - histogram_5++; - else - histogram_6++; - - if (jitter > max_jitter) - max_jitter = jitter; - } -#endif - idx_r = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, ridx); - idx_w = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, widx); - - if (idx_r != idx_w) { - no_change = false; - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, ridx, idx_r, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, widx, idx_w, 1); - } - - SCSC_HIP4_SAMPLER_INT_BH(hip_priv->minor, 2); - while (idx_r != idx_w) { - struct mbulk *m; - u16 colour; - - ref = ctrl->q[HIP4_MIF_Q_FH_RFB].array[idx_r]; - SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_FH_RFB); -#ifdef CONFIG_SCSC_WLAN_DEBUG - hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_FH_RFB] = hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_FH_RFB] + 1; -#endif - mem = scsc_mx_service_mif_addr_to_ptr(service, ref); - m = (struct mbulk *)mem; - if (!m) { - SLSI_ERR_NODEV("FB: Mbulk is NULL 0x%x\n", ref); - goto consume_fb_mbulk; - } - /* colour is defined as: */ - /* u16 register bits: - * 0 - do not use - * [2:1] - vif - * [7:3] - peer_index - * [10:8] - ac queue - */ - colour = ((m->clas & 0xc0) << 2) | (m->pid & 0xfe); - /* Account ONLY for data RFB */ - if ((m->pid & 0x1) == MBULK_POOL_ID_DATA) { -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0x6) >> 1, (colour & 0xf8) >> 3); - /* to profile round-trip */ - { - u16 host_tag; - u8 *get_host_tag; - /* This is a nasty way of getting the host_tag without involving mbulk processing - * This hostag value should also be include in the cb descriptor which goes to - * mbulk descriptor (no room left at the moment) - */ - get_host_tag = (u8 *)m; - host_tag = get_host_tag[37] << 8 | get_host_tag[36]; - SCSC_HIP4_SAMPLER_PKT_TX_FB(hip->hip_priv->minor, host_tag); - } -#endif - /* Ignore return value */ - slsi_hip_tx_done(sdev, colour); - } - mbulk_free_virt_host(m); -consume_fb_mbulk: - /* Increase index */ - idx_r++; - idx_r &= (MAX_NUM - 1); - hip4_update_index(hip, HIP4_MIF_Q_FH_RFB, ridx, idx_r); - } - SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv->minor, 2); - - atomic_set(&hip->hip_priv->in_rx, 4); - - idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, ridx); - idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, widx); - - if (idx_r != idx_w) { - no_change = false; - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, ridx, idx_r, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, widx, idx_w, 1); - } - - SCSC_HIP4_SAMPLER_INT_BH(hip_priv->minor, 1); - while (idx_r != idx_w) { - struct sk_buff *skb; - /* TODO: currently the max number to be freed is 2. In future - * implementations (i.e. AMPDU) this number may be bigger - * list of mbulks to be freedi - */ - scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 }; - u8 i = 0; - - /* Catch-up with idx_w */ - ref = ctrl->q[HIP4_MIF_Q_TH_CTRL].array[idx_r]; - SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_CTRL); -#ifdef CONFIG_SCSC_WLAN_DEBUG - hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_CTRL] = hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_CTRL] + 1; -#endif - mem = scsc_mx_service_mif_addr_to_ptr(service, ref); - m = (struct mbulk *)(mem); - if (!m) { - SLSI_ERR_NODEV("Ctrl: Mbulk is NULL 0x%x\n", ref); - goto consume_ctl_mbulk; - } - /* Process Control Signal */ - skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, false); - if (!skb) { - SLSI_ERR_NODEV("Ctrl: Error parsing or allocating skb\n"); - hip4_dump_dbg(hip, m, skb, service); - goto consume_ctl_mbulk; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (m->flag & MBULK_F_WAKEUP) { - SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x:\n", fapi_get_sigid(skb)); - SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len); - } -#else - if (m->flag & MBULK_F_WAKEUP) - SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x\n", fapi_get_sigid(skb)); -#endif - -#if defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) || defined(CONFIG_SCSC_WLAN_DEBUG) - id = fapi_get_sigid(skb); -#endif -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - /* log control signal, not unidata not debug */ - if (fapi_is_mlme(skb)) - SCSC_HIP4_SAMPLER_SIGNAL_CTRLRX(hip_priv->minor, (id & 0xff00) >> 8, id & 0xff); -#endif -#ifdef CONFIG_SCSC_WLAN_DEBUG - hip4_history_record_add(TH, id); -#endif - if (slsi_hip_rx(sdev, skb) < 0) { - SLSI_ERR_NODEV("Ctrl: Error detected slsi_hip_rx\n"); - hip4_dump_dbg(hip, m, skb, service); - slsi_kfree_skb(skb); - } -consume_ctl_mbulk: - /* Increase index */ - idx_r++; - idx_r &= (MAX_NUM - 1); - - /* Go through the list of references to free */ - while ((ref = to_free[i++])) { - /* Set the number of retries */ - retry = FB_NO_SPC_NUM_RET; - /* return to the firmware */ - while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) { - SLSI_WARN_NODEV("Ctrl: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET); - spin_unlock_bh(&hip_priv->rx_lock); - msleep(FB_NO_SPC_SLEEP_MS); - spin_lock_bh(&hip_priv->rx_lock); - retry--; - if (retry == 0) - SLSI_ERR_NODEV("Ctrl: FB has not been freed for %d ms\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_SLEEP_MS); - SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB); - } - } - hip4_update_index(hip, HIP4_MIF_Q_TH_CTRL, ridx, idx_r); - } - - SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv->minor, 1); - - if (rx_flowcontrol) - goto skip_data_q; - - atomic_set(&hip->hip_priv->in_rx, 5); - - idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, ridx); - idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, widx); - - if (idx_r != idx_w) { - packets_total = 0; - no_change = false; - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, ridx, idx_r, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, widx, idx_w, 1); -#ifdef CONFIG_SCSC_WLAN_DEBUG - /* Compute DAT histogram */ - { - u8 num_packets = (idx_w - idx_r) % 256; - - if (num_packets <= HISTO_1_DATA) - histogram_1_data++; - else if (num_packets > HISTO_1_DATA && num_packets <= HISTO_2_DATA) - histogram_2_data++; - else if (num_packets > HISTO_2_DATA && num_packets <= HISTO_3_DATA) - histogram_3_data++; - else if (num_packets > HISTO_3_DATA && num_packets <= HISTO_4_DATA) - histogram_4_data++; - else if (num_packets > HISTO_4_DATA && num_packets <= HISTO_5_DATA) - histogram_5_data++; - else - histogram_6_data++; - if (num_packets > max_data) - max_data = num_packets; - } -#endif - } - - SCSC_HIP4_SAMPLER_INT_BH(hip_priv->minor, 0); - while (idx_r != idx_w) { - struct sk_buff *skb; - /* TODO: currently the max number to be freed is 2. In future - * implementations (i.e. AMPDU) this number may be bigger - */ - /* list of mbulks to be freed */ - scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 }; - u8 i = 0; - - packets_total++; - /* Catch-up with idx_w */ - ref = ctrl->q[HIP4_MIF_Q_TH_DAT].array[idx_r]; - SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_DAT); -#ifdef CONFIG_SCSC_WLAN_DEBUG - hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_DAT] = hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_DAT] + 1; -#endif - mem = scsc_mx_service_mif_addr_to_ptr(service, ref); - m = (struct mbulk *)(mem); - if (!m) { - SLSI_ERR_NODEV("Dat: Mbulk is NULL 0x%x\n", ref); - goto consume_dat_mbulk; - } - - skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, false); - if (!skb) { - SLSI_ERR_NODEV("Dat: Error parsing or allocating skb\n"); - hip4_dump_dbg(hip, m, skb, service); - goto consume_dat_mbulk; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (m->flag & MBULK_F_WAKEUP) { - SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n"); - SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len); - } -#else - if (m->flag & MBULK_F_WAKEUP) { - SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n"); - SCSC_BIN_TAG_INFO(BINARY, skb->data, fapi_get_siglen(skb) + ETH_HLEN); - } -#endif -#ifdef CONFIG_SCSC_WLAN_DEBUG - id = fapi_get_sigid(skb); - hip4_history_record_add(TH, id); -#endif - if (slsi_hip_rx(sdev, skb) < 0) { - SLSI_ERR_NODEV("Dat: Error detected slsi_hip_rx\n"); - hip4_dump_dbg(hip, m, skb, service); - slsi_kfree_skb(skb); - } -consume_dat_mbulk: - /* Increase index */ - idx_r++; - idx_r &= (MAX_NUM - 1); - - /* Go through the list of references to free */ - while ((ref = to_free[i++])) { - /* Set the number of retries */ - retry = FB_NO_SPC_NUM_RET; - /* return to the firmware */ - while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) { - SLSI_WARN_NODEV("Dat: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET); - spin_unlock_bh(&hip_priv->rx_lock); - msleep(FB_NO_SPC_SLEEP_MS); - spin_lock_bh(&hip_priv->rx_lock); - retry--; - if (retry == 0) - SLSI_ERR_NODEV("Dat: FB has not been freed for %d ms\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_SLEEP_MS); - SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB); - } - } - - hip4_update_index(hip, HIP4_MIF_Q_TH_DAT, ridx, idx_r); - - /* read again the write index */ - if ((idx_r == idx_w) && (packets_total < HIP4_POLLING_MAX_PACKETS)) { - u8 old_idx = idx_w; - - idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, widx); - if (idx_w != old_idx) { - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, ridx, idx_r, 1); - SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, widx, idx_w, 1); - } - } - } - SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv->minor, 0); - - if (no_change) - atomic_inc(&hip->hip_priv->stats.spurious_irqs); - -skip_data_q: - if (!atomic_read(&hip->hip_priv->closing)) { - /* Reset status variable. DO THIS BEFORE UNMASKING!!!*/ - atomic_set(&hip->hip_priv->watchdog_timer_active, 0); - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); - } - -#ifdef CONFIG_ANDROID - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock", WL_REASON_RX); - } -#endif - bh_end = ktime_get(); - atomic_set(&hip->hip_priv->in_rx, 0); - spin_unlock_bh(&hip_priv->rx_lock); -} - -/* IRQ handler for hip4. The function runs in Interrupt context, so all the - * asssumptions related to interrupt should be applied (sleep, fast,...) - */ -static void hip4_irq_handler(int irq, void *data) -{ - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - - (void)irq; /* unused */ - - if (!hip || !sdev || !sdev->service || !hip->hip_priv) - return; - - SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 0); - SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 1); - SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 2); - intr_received = ktime_get(); - -#ifdef CONFIG_ANDROID - if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock)) { - wake_lock_timeout(&hip->hip_priv->hip4_wake_lock, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS)); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock", WL_REASON_RX); - } -#endif - /* if wd timer is active system might be in trouble as it should be - * cleared in the BH. Ignore updating the timer - */ - if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) { - atomic_set(&hip->hip_priv->watchdog_timer_active, 1); - mod_timer(&hip->hip_priv->watchdog, jiffies + HZ); - } else { - SLSI_ERR_NODEV("INT triggered while WDT is active\n"); - SLSI_ERR_NODEV("bh_init %lld\n", ktime_to_ns(bh_init)); - SLSI_ERR_NODEV("bh_end %lld\n", ktime_to_ns(bh_end)); - SLSI_ERR_NODEV("hip4_wq work_busy %d\n", work_busy(&hip->hip_priv->intr_wq)); - SLSI_ERR_NODEV("hip4_priv->in_rx %d\n", atomic_read(&hip->hip_priv->in_rx)); - } - /* If system is not in suspend, mask interrupt to avoid interrupt storm and let BH run */ - if (!atomic_read(&hip->hip_priv->in_suspend)) { - scsc_service_mifintrbit_bit_mask(sdev->service, hip->hip_priv->intr_tohost); - hip->hip_priv->storm_count = 0; - } else if (++hip->hip_priv->storm_count >= MAX_STORM) { - /* A MAX_STORM number of interrupts has been received - * when platform was in suspend. This indicates FW interrupt activity - * that should resume the hip4, so it is safe to mask to avoid - * interrupt storm. - */ - hip->hip_priv->storm_count = 0; - scsc_service_mifintrbit_bit_mask(sdev->service, hip->hip_priv->intr_tohost); - } - - atomic_inc(&hip->hip_priv->stats.irqs); - - if (hip4_system_wq) - schedule_work(&hip->hip_priv->intr_wq); - else - queue_work(hip->hip_priv->hip4_workq, &hip->hip_priv->intr_wq); - - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(sdev->service, hip->hip_priv->intr_tohost); - SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 0); - SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 1); - SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 2); -} - -#ifdef CONFIG_SCSC_QOS -static void hip4_pm_qos_work(struct work_struct *data) -{ - struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, pm_qos_work); - struct slsi_hip4 *hip = hip_priv->hip; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - u8 state; - - if (!sdev || !sdev->service) { - WARN_ON(1); - return; - } - - SLSI_DBG1(sdev, SLSI_HIP, "update to state %d\n", hip_priv->pm_qos_state); - spin_lock_bh(&hip_priv->pm_qos_lock); - state = hip_priv->pm_qos_state; - spin_unlock_bh(&hip_priv->pm_qos_lock); - scsc_service_pm_qos_update_request(sdev->service, state); -} - -static void hip4_traffic_monitor_cb(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx) -{ - struct slsi_hip4 *hip = (struct slsi_hip4 *)client_ctx; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - - if (!sdev) - return; - - spin_lock_bh(&hip->hip_priv->pm_qos_lock); - SLSI_DBG1(sdev, SLSI_HIP, "event (state:%u, tput_tx:%u bps, tput_rx:%u bps)\n", state, tput_tx, tput_rx); - if (state == TRAFFIC_MON_CLIENT_STATE_HIGH) - hip->hip_priv->pm_qos_state = SCSC_QOS_MAX; - else if (state == TRAFFIC_MON_CLIENT_STATE_MID) - hip->hip_priv->pm_qos_state = SCSC_QOS_MED; - else - hip->hip_priv->pm_qos_state = SCSC_QOS_DISABLED; - - spin_unlock_bh(&hip->hip_priv->pm_qos_lock); - - schedule_work(&hip->hip_priv->pm_qos_work); -} -#endif - -#ifdef CONFIG_SCSC_LOGRING -static void hip4_traffic_monitor_logring_cb(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx) -{ - struct hip4_priv *hip_priv = (struct hip4_priv *)client_ctx; - struct slsi_hip4 *hip = hip_priv->hip; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - - if (!sdev) - return; - - SLSI_DBG1(sdev, SLSI_HIP, "event (state:%u, tput_tx:%u bps, tput_rx:%u bps)\n", state, tput_tx, tput_rx); - if (state == TRAFFIC_MON_CLIENT_STATE_HIGH || state == TRAFFIC_MON_CLIENT_STATE_MID) { - if (hip4_dynamic_logging) - scsc_logring_enable(false); - } else { - scsc_logring_enable(true); - } -} -#endif - -int hip4_init(struct slsi_hip4 *hip) -{ - void *hip_ptr; - struct hip4_hip_control *hip_control; - struct scsc_service *service; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - scsc_mifram_ref ref, ref_scoreboard; - int i; - int ret; - u32 total_mib_len; - u32 mib_file_offset; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - struct net_device *dev; -#endif - - if (!sdev || !sdev->service) - return -EINVAL; - - hip->hip_priv = kzalloc(sizeof(*hip->hip_priv), GFP_ATOMIC); - if (!hip->hip_priv) - return -ENOMEM; - - SLSI_INFO_NODEV("HIP4_WLAN_CONFIG_SIZE (%d)\n", HIP4_WLAN_CONFIG_SIZE); - SLSI_INFO_NODEV("HIP4_WLAN_MIB_SIZE (%d)\n", HIP4_WLAN_MIB_SIZE); - SLSI_INFO_NODEV("HIP4_WLAN_TX_DAT_SIZE (%d)\n", HIP4_WLAN_TX_DAT_SIZE); - SLSI_INFO_NODEV("HIP4_WLAN_TX_CTL_SIZE (%d)\n", HIP4_WLAN_TX_CTL_SIZE); - SLSI_INFO_NODEV("HIP4_WLAN_RX_SIZE (%d)\n", HIP4_WLAN_RX_SIZE); - SLSI_INFO_NODEV("HIP4_WLAN_TOTAL_MEM (%d)\n", HIP4_WLAN_TOTAL_MEM); - SLSI_INFO_NODEV("HIP4_DAT_SLOTS (%d)\n", HIP4_DAT_SLOTS); - SLSI_INFO_NODEV("HIP4_CTL_SLOTS (%d)\n", HIP4_CTL_SLOTS); -#ifdef CONFIG_SCSC_WLAN_DEBUG - memset(&hip->hip_priv->stats, 0, sizeof(hip->hip_priv->stats)); - hip->hip_priv->stats.start = ktime_get(); - hip->hip_priv->stats.procfs_dir = proc_mkdir("driver/hip4", NULL); - if (hip->hip_priv->stats.procfs_dir) { - proc_create_data("info", S_IRUSR | S_IRGRP, - hip->hip_priv->stats.procfs_dir, &hip4_procfs_stats_fops, hip); - proc_create_data("history", S_IRUSR | S_IRGRP, - hip->hip_priv->stats.procfs_dir, &hip4_procfs_history_fops, hip); - proc_create_data("jitter", S_IRUSR | S_IRGRP, - hip->hip_priv->stats.procfs_dir, &hip4_procfs_jitter_fops, hip); - } - - hip->hip_priv->minor = hip4_sampler_register_hip(sdev->maxwell_core); - if (hip->hip_priv->minor < SCSC_HIP4_INTERFACES) { - SLSI_DBG1_NODEV(SLSI_HIP, "registered with minor %d\n", hip->hip_priv->minor); - sdev->minor_prof = hip->hip_priv->minor; - } else { - SLSI_DBG1_NODEV(SLSI_HIP, "hip4_sampler is not enabled\n"); - } -#endif - - /* Used in the workqueue */ - hip->hip_priv->hip = hip; - - service = sdev->service; - - hip->hip_priv->host_pool_id_dat = MBULK_POOL_ID_DATA; - hip->hip_priv->host_pool_id_ctl = MBULK_POOL_ID_CTRL; - - /* hip_ref contains the reference of the start of shared memory allocated for WLAN */ - /* hip_ptr is the kernel address of hip_ref*/ - hip_ptr = scsc_mx_service_mif_addr_to_ptr(service, hip->hip_ref); - -#ifdef CONFIG_SCSC_WLAN_DEBUG - /* Configure mbulk allocator - Data QUEUES */ - ret = mbulk_pool_add(MBULK_POOL_ID_DATA, hip_ptr + HIP4_WLAN_TX_DAT_OFFSET, - hip_ptr + HIP4_WLAN_TX_DAT_OFFSET + HIP4_WLAN_TX_DAT_SIZE, - (HIP4_WLAN_TX_DAT_SIZE / HIP4_DAT_SLOTS) - sizeof(struct mbulk), 5, - hip->hip_priv->minor); - if (ret) - return ret; - - /* Configure mbulk allocator - Control QUEUES */ - ret = mbulk_pool_add(MBULK_POOL_ID_CTRL, hip_ptr + HIP4_WLAN_TX_CTL_OFFSET, - hip_ptr + HIP4_WLAN_TX_CTL_OFFSET + HIP4_WLAN_TX_CTL_SIZE, - (HIP4_WLAN_TX_CTL_SIZE / HIP4_CTL_SLOTS) - sizeof(struct mbulk), 0, - hip->hip_priv->minor); - if (ret) - return ret; -#else - /* Configure mbulk allocator - Data QUEUES */ - ret = mbulk_pool_add(MBULK_POOL_ID_DATA, hip_ptr + HIP4_WLAN_TX_DAT_OFFSET, - hip_ptr + HIP4_WLAN_TX_DAT_OFFSET + HIP4_WLAN_TX_DAT_SIZE, - (HIP4_WLAN_TX_DAT_SIZE / HIP4_DAT_SLOTS) - sizeof(struct mbulk), 5); - if (ret) - return ret; - - /* Configure mbulk allocator - Control QUEUES */ - ret = mbulk_pool_add(MBULK_POOL_ID_CTRL, hip_ptr + HIP4_WLAN_TX_CTL_OFFSET, - hip_ptr + HIP4_WLAN_TX_CTL_OFFSET + HIP4_WLAN_TX_CTL_SIZE, - (HIP4_WLAN_TX_CTL_SIZE / HIP4_CTL_SLOTS) - sizeof(struct mbulk), 0); - if (ret) - return ret; -#endif - - /* Reset hip_control table */ - memset(hip_ptr, 0, sizeof(struct hip4_hip_control)); - - /* Reset Sample q values sending 0xff */ - SCSC_HIP4_SAMPLER_RESET(hip->hip_priv->minor); - - /***** VERSION 4 *******/ - /* TOHOST Handler allocator */ -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - /* Q0 FH CTRL */ - hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_CTRL] = MIF_NO_IRQ; - /* Q1 FH DATA */ - hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_DAT] = MIF_NO_IRQ; - /* Q5 TH RFB */ - hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_RFB] = MIF_NO_IRQ; - /* Q2 FH FB */ - hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB] = - scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler_fb, hip); - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]); - /* Q3 TH CTRL */ - hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL] = - scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler_ctrl, hip); - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]); - /* Q4 TH DAT */ - hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT] = - scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler_dat, hip); - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]); - - rcu_read_lock(); - /* one NAPI instance is ok for multiple netdev devices */ - dev = slsi_get_netdev_rcu(sdev, SLSI_NET_INDEX_WLAN); - if (!dev) { - SLSI_ERR(sdev, "netdev No longer exists\n"); - rcu_read_unlock(); - return -EINVAL; - } - netif_napi_add(dev, &hip->hip_priv->napi, hip4_napi_poll, NAPI_POLL_WEIGHT); - rcu_read_unlock(); -#endif - /* TOHOST Handler allocator */ - hip->hip_priv->intr_tohost = - scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler, hip); - - /* Mask the interrupt to prevent intr been kicked during start */ - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost); - - /* FROMHOST Handler allocator */ - hip->hip_priv->intr_fromhost = - scsc_service_mifintrbit_alloc_fromhost(service, SCSC_MIFINTR_TARGET_R4); - - /* Get hip_control pointer on shared memory */ - hip_control = (struct hip4_hip_control *)(hip_ptr + - HIP4_WLAN_CONFIG_OFFSET); - - /* Initialize scoreboard */ - if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->scoreboard, &ref_scoreboard)) - return -EFAULT; - - /* Calculate total space used by wlan*.hcf files */ - for (i = 0, total_mib_len = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++) - total_mib_len += sdev->mib[i].mib_len; - - /* Copy MIB content in shared memory if any */ - /* Clear the area to avoid picking up old values */ - memset(hip_ptr + HIP4_WLAN_MIB_OFFSET, 0, HIP4_WLAN_MIB_SIZE); - - if (total_mib_len > HIP4_WLAN_MIB_SIZE) { - SLSI_ERR_NODEV("MIB size (%d), is bigger than the MIB AREA (%d). Aborting memcpy\n", total_mib_len, HIP4_WLAN_MIB_SIZE); - hip_control->config_v4.mib_loc = 0; - hip_control->config_v4.mib_sz = 0; - hip_control->config_v5.mib_loc = 0; - hip_control->config_v5.mib_sz = 0; - total_mib_len = 0; - } else if (total_mib_len) { - SLSI_INFO_NODEV("Loading MIB into shared memory, size (%d)\n", total_mib_len); - /* Load each MIB file into shared DRAM region */ - for (i = 0, mib_file_offset = 0; - i < SLSI_WLAN_MAX_MIB_FILE; - i++) { - SLSI_INFO_NODEV("Loading MIB %d into shared memory, offset (%d), size (%d), total (%d)\n", i, mib_file_offset, sdev->mib[i].mib_len, total_mib_len); - if (sdev->mib[i].mib_len) { - memcpy((u8 *)hip_ptr + HIP4_WLAN_MIB_OFFSET + mib_file_offset, sdev->mib[i].mib_data, sdev->mib[i].mib_len); - mib_file_offset += sdev->mib[i].mib_len; - } - } - hip_control->config_v4.mib_loc = hip->hip_ref + HIP4_WLAN_MIB_OFFSET; - hip_control->config_v4.mib_sz = total_mib_len; - hip_control->config_v5.mib_loc = hip->hip_ref + HIP4_WLAN_MIB_OFFSET; - hip_control->config_v5.mib_sz = total_mib_len; - } else { - hip_control->config_v4.mib_loc = 0; - hip_control->config_v4.mib_sz = 0; - hip_control->config_v5.mib_loc = 0; - hip_control->config_v5.mib_sz = 0; - } - - /* Initialize hip_control table for version 4 */ - /***** VERSION 4 *******/ - hip_control->config_v4.magic_number = 0xcaba0401; - hip_control->config_v4.hip_config_ver = 4; - hip_control->config_v4.config_len = sizeof(struct hip4_hip_config_version_4); - hip_control->config_v4.host_cache_line = 64; - hip_control->config_v4.host_buf_loc = hip->hip_ref + HIP4_WLAN_TX_OFFSET; - hip_control->config_v4.host_buf_sz = HIP4_WLAN_TX_SIZE; - hip_control->config_v4.fw_buf_loc = hip->hip_ref + HIP4_WLAN_RX_OFFSET; - hip_control->config_v4.fw_buf_sz = HIP4_WLAN_RX_SIZE; - hip_control->config_v4.log_config_loc = 0; - - hip_control->config_v4.mif_fh_int_n = hip->hip_priv->intr_fromhost; - for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) { -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - hip_control->config_v4.mif_th_int_n[i] = hip->hip_priv->intr_tohost_mul[i]; -#else - hip_control->config_v4.mif_th_int_n[i] = hip->hip_priv->intr_tohost; -#endif - } - - hip_control->config_v4.scbrd_loc = (u32)ref_scoreboard; - hip_control->config_v4.q_num = 6; - hip_control->config_v4.q_len = 256; - hip_control->config_v4.q_idx_sz = 1; - /* Initialize q relative positions */ - for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) { - if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->q[i].array, &ref)) - return -EFAULT; - hip_control->config_v4.q_loc[i] = (u32)ref; - } - /***** END VERSION 4 *******/ - - /* Initialize hip_control table for version 5 */ - /***** VERSION 5 *******/ - hip_control->config_v5.magic_number = 0xcaba0401; - hip_control->config_v5.hip_config_ver = 5; - hip_control->config_v5.config_len = sizeof(struct hip4_hip_config_version_5); - hip_control->config_v5.host_cache_line = 64; - hip_control->config_v5.host_buf_loc = hip->hip_ref + HIP4_WLAN_TX_OFFSET; - hip_control->config_v5.host_buf_sz = HIP4_WLAN_TX_SIZE; - hip_control->config_v5.fw_buf_loc = hip->hip_ref + HIP4_WLAN_RX_OFFSET; - hip_control->config_v5.fw_buf_sz = HIP4_WLAN_RX_SIZE; - hip_control->config_v5.log_config_loc = 0; - hip_control->config_v5.mif_fh_int_n = hip->hip_priv->intr_fromhost; - hip_control->config_v5.mif_th_int_n = hip->hip_priv->intr_tohost; - hip_control->config_v5.q_num = 6; - hip_control->config_v5.q_len = 256; - hip_control->config_v5.q_idx_sz = 1; - hip_control->config_v5.scbrd_loc = (u32)ref_scoreboard; /* scoreborad location */ - - /* Initialize q relative positions */ - for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) { - if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->q[i].array, &ref)) - return -EFAULT; - hip_control->config_v5.q_loc[i] = (u32)ref; - } - /***** END VERSION 5 *******/ - - /* Initialzie hip_init configuration */ - hip_control->init.magic_number = 0xcaaa0400; - if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->config_v4, &ref)) - return -EFAULT; - hip_control->init.version_a_ref = ref; - - if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->config_v5, &ref)) - return -EFAULT; - hip_control->init.version_b_ref = ref; - /* End hip_init configuration */ - - hip->hip_control = hip_control; - hip->hip_priv->scbrd_base = &hip_control->scoreboard; - - spin_lock_init(&hip->hip_priv->rx_lock); - atomic_set(&hip->hip_priv->in_rx, 0); - spin_lock_init(&hip->hip_priv->tx_lock); - atomic_set(&hip->hip_priv->in_tx, 0); - - /* Init work structs */ - hip->hip_priv->hip4_workq = create_singlethread_workqueue("hip4_work"); - if (!hip->hip_priv->hip4_workq) { - SLSI_ERR_NODEV("Error creating singlethread_workqueue\n"); - return -ENOMEM; - } -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - tasklet_init(&hip->hip_priv->intr_tasklet, hip4_irq_data_tasklet, (unsigned long)hip); - INIT_WORK(&hip->hip_priv->intr_wq_ctrl, hip4_wq_ctrl); - INIT_WORK(&hip->hip_priv->intr_wq_fb, hip4_wq_fb); -#endif - INIT_WORK(&hip->hip_priv->intr_wq, hip4_wq); - - rwlock_init(&hip->hip_priv->rw_scoreboard); - - /* Setup watchdog timer */ - atomic_set(&hip->hip_priv->watchdog_timer_active, 0); - spin_lock_init(&hip->hip_priv->watchdog_lock); -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - timer_setup(&hip->hip_priv->watchdog, hip4_watchdog, 0); -#else - setup_timer(&hip->hip_priv->watchdog, hip4_watchdog, (unsigned long)hip); -#endif - - atomic_set(&hip->hip_priv->gmod, HIP4_DAT_SLOTS); - atomic_set(&hip->hip_priv->gactive, 1); - spin_lock_init(&hip->hip_priv->gbot_lock); - hip->hip_priv->saturated = 0; - -#ifdef CONFIG_ANDROID -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - wake_lock_init(&hip->hip_priv->hip4_wake_lock_tx, WAKE_LOCK_SUSPEND, "hip4_wake_lock_tx"); - wake_lock_init(&hip->hip_priv->hip4_wake_lock_ctrl, WAKE_LOCK_SUSPEND, "hip4_wake_lock_ctrl"); - wake_lock_init(&hip->hip_priv->hip4_wake_lock_data, WAKE_LOCK_SUSPEND, "hip4_wake_lock_data"); -#endif - wake_lock_init(&hip->hip_priv->hip4_wake_lock, WAKE_LOCK_SUSPEND, "hip4_wake_lock"); -#endif -#ifdef CONFIG_SCSC_SMAPPER - /* Init SMAPPER */ - if (hip4_smapper_enable) { - if (hip4_smapper_init(sdev, hip)) { - SLSI_ERR_NODEV("Error on hip4_smapper init\n"); - hip4_smapper_is_enabled = false; - } else { - hip4_smapper_is_enabled = true; - } - } -#endif -#ifdef CONFIG_SCSC_QOS - /* setup for PM QoS */ - spin_lock_init(&hip->hip_priv->pm_qos_lock); - - if (hip4_qos_enable) { - if (!scsc_service_pm_qos_add_request(service, SCSC_QOS_DISABLED)) { - /* register to traffic monitor for throughput events */ - if (slsi_traffic_mon_client_register(sdev, hip, TRAFFIC_MON_CLIENT_MODE_EVENTS, (hip4_qos_med_tput_in_mbps * 1000 * 1000), (hip4_qos_max_tput_in_mbps * 1000 * 1000), hip4_traffic_monitor_cb)) - SLSI_WARN(sdev, "failed to add PM QoS client to traffic monitor\n"); - else - INIT_WORK(&hip->hip_priv->pm_qos_work, hip4_pm_qos_work); - } else { - SLSI_WARN(sdev, "failed to add PM QoS request\n"); - } - } -#endif -#ifdef CONFIG_SCSC_LOGRING - /* register to traffic monitor for dynamic logring logging */ - if (slsi_traffic_mon_client_register(sdev, hip->hip_priv, TRAFFIC_MON_CLIENT_MODE_EVENTS, 0, (hip4_dynamic_logging_tput_in_mbps * 1000 * 1000), hip4_traffic_monitor_logring_cb)) - SLSI_WARN(sdev, "failed to add Logring client to traffic monitor\n"); -#endif - return 0; -} - -/** - * This function returns the number of free slots available to - * transmit control packet. - */ -int hip4_free_ctrl_slots_count(struct slsi_hip4 *hip) -{ - return mbulk_pool_get_free_count(MBULK_POOL_ID_CTRL); -} - -/** - * This function is in charge to transmit a frame through the HIP. - * It does NOT take ownership of the SKB unless it successfully transmit it; - * as a consequence skb is NOT freed on error. - * We return ENOSPC on queue related troubles in order to trigger upper - * layers of kernel to requeue/retry. - * We free ONLY locally-allocated stuff. - */ -int scsc_wifi_transmit_frame(struct slsi_hip4 *hip, bool ctrl_packet, struct sk_buff *skb) -{ - struct scsc_service *service; - scsc_mifram_ref offset; - struct mbulk *m; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - struct fapi_signal_header *fapi_header; - int ret = 0; -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - struct slsi_skb_cb *cb = slsi_skb_cb_get(skb); -#endif -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; -#endif - - if (!hip || !sdev || !sdev->service || !skb || !hip->hip_priv) - return -EINVAL; - - spin_lock_bh(&hip->hip_priv->tx_lock); - atomic_set(&hip->hip_priv->in_tx, 1); - -#ifdef CONFIG_ANDROID -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); - if (conf_hip4_ver == 4) { - if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) { - wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_tx, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS)); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_tx", WL_REASON_TX); - } - } else { - if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock)) { - wake_lock_timeout(&hip->hip_priv->hip4_wake_lock, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS)); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock", WL_REASON_TX); - } - } -#else - if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock)) { - wake_lock_timeout(&hip->hip_priv->hip4_wake_lock, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS)); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock", WL_REASON_TX); - } -#endif -#endif - service = sdev->service; - - fapi_header = (struct fapi_signal_header *)skb->data; - - m = hip4_skb_to_mbulk(hip->hip_priv, skb, ctrl_packet); - if (!m) { - SCSC_HIP4_SAMPLER_MFULL(hip->hip_priv->minor); - ret = -ENOSPC; - SLSI_ERR_NODEV("mbulk is NULL\n"); - goto error; - } - - if (scsc_mx_service_mif_ptr_to_addr(service, m, &offset) < 0) { - mbulk_free_virt_host(m); - ret = -EFAULT; - SLSI_ERR_NODEV("Incorrect reference memory\n"); - goto error; - } - - if (hip4_q_add_signal(hip, ctrl_packet ? HIP4_MIF_Q_FH_CTRL : HIP4_MIF_Q_FH_DAT, offset, service)) { - SCSC_HIP4_SAMPLER_QFULL(hip->hip_priv->minor, ctrl_packet ? HIP4_MIF_Q_FH_CTRL : HIP4_MIF_Q_FH_DAT); - mbulk_free_virt_host(m); - ret = -ENOSPC; - SLSI_ERR_NODEV("No space\n"); - goto error; - } - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - /* colour is defined as: */ - /* u8 register bits: - * 0 - do not use - * [2:1] - vif - * [7:3] - peer_index - */ - if (ctrl_packet) { - /* Record control signal */ - SCSC_HIP4_SAMPLER_SIGNAL_CTRLTX(hip->hip_priv->minor, (fapi_header->id & 0xff00) >> 8, fapi_header->id & 0xff); - } else { - SCSC_HIP4_SAMPLER_PKT_TX_HIP4(hip->hip_priv->minor, fapi_get_u16(skb, u.ma_unitdata_req.host_tag)); - SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 1, (cb->colour & 0x6) >> 1, (cb->colour & 0xf8) >> 3); - } -#endif -#ifdef CONFIG_SCSC_WLAN_DEBUG - hip4_history_record_add(FH, fapi_header->id); -#endif - - /* Here we push a copy of the bare skb TRANSMITTED data also to the logring - * as a binary record. Note that bypassing UDI subsystem as a whole - * means we are losing: - * UDI filtering / UDI Header INFO / UDI QueuesFrames Throttling / - * UDI Skb Asynchronous processing - * We keep separated DATA/CTRL paths. - */ - if (ctrl_packet) - SCSC_BIN_TAG_DEBUG(BIN_WIFI_CTRL_TX, skb->data, skb_headlen(skb)); - else - SCSC_BIN_TAG_DEBUG(BIN_WIFI_DATA_TX, skb->data, skb_headlen(skb)); - /* slsi_log_clients_log_signal_fast: skb is copied to all the log clients */ - slsi_log_clients_log_signal_fast(sdev, &sdev->log_clients, skb, SLSI_LOG_DIRECTION_FROM_HOST); - slsi_kfree_skb(skb); - atomic_set(&hip->hip_priv->in_tx, 0); - spin_unlock_bh(&hip->hip_priv->tx_lock); - return 0; - -error: -#ifdef CONFIG_ANDROID -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - if (conf_hip4_ver == 4) { - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock_tx); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_tx", WL_REASON_TX); - } - } else { - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock", WL_REASON_TX); - } - } -#else - if (wake_lock_active(&hip->hip_priv->hip4_wake_lock)) { - wake_unlock(&hip->hip_priv->hip4_wake_lock); - SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock", WL_REASON_TX); - } -#endif -#endif - atomic_set(&hip->hip_priv->in_tx, 0); - spin_unlock_bh(&hip->hip_priv->tx_lock); - return ret; -} - -/* HIP4 has been initialize, setup with values - * provided by FW - */ -int hip4_setup(struct slsi_hip4 *hip) -{ - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - struct scsc_service *service; - u32 conf_hip4_ver = 0; - - if (!sdev || !sdev->service) - return -EIO; - - if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED) - return -EIO; - - service = sdev->service; - - /* Get the Version reported by the FW */ - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - /* Check if the version is supported. And get the index */ - /* This is hardcoded and may change in future versions */ - if (conf_hip4_ver != 4 && conf_hip4_ver != 3) { - SLSI_ERR_NODEV("FW Version %d not supported\n", conf_hip4_ver); - return -EIO; - } - - if (conf_hip4_ver == 4) { - hip->hip_priv->unidat_req_headroom = - scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_headroom, 4); - hip->hip_priv->unidat_req_tailroom = - scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_tailroom, 4); - hip->hip_priv->version = 4; - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - napi_enable(&hip->hip_priv->napi); -#endif - } else { - /* version 5 */ - hip->hip_priv->unidat_req_headroom = - scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_headroom, 5); - hip->hip_priv->unidat_req_tailroom = - scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_tailroom, 5); - hip->hip_priv->version = 5; - } - /* Unmask interrupts - now host should handle them */ - atomic_set(&hip->hip_priv->stats.irqs, 0); - atomic_set(&hip->hip_priv->stats.spurious_irqs, 0); - atomic_set(&sdev->debug_inds, 0); - - atomic_set(&hip->hip_priv->closing, 0); - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - if (conf_hip4_ver == 4) { - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]); - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]); - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]); - } else { - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); - } -#else - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); -#endif - return 0; -} - -/* On suspend hip4 needs to ensure that TH interrupts *are* unmasked */ -void hip4_suspend(struct slsi_hip4 *hip) -{ - struct slsi_dev *sdev; - struct scsc_service *service; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; -#endif - - if (!hip || !hip->hip_priv) - return; - - sdev = container_of(hip, struct slsi_dev, hip4_inst); - if (!sdev || !sdev->service) - return; - - if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED) - return; - - service = sdev->service; - - slsi_log_client_msg(sdev, UDI_DRV_SUSPEND_IND, 0, NULL); - SCSC_HIP4_SAMPLER_SUSPEND(hip->hip_priv->minor); - - atomic_set(&hip->hip_priv->in_suspend, 1); - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - - if (conf_hip4_ver == 4) { - for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++) - if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ) - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]); - } else { - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); - } -#else - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); -#endif -} - -void hip4_resume(struct slsi_hip4 *hip) -{ - struct slsi_dev *sdev; - struct scsc_service *service; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; -#endif - - if (!hip || !hip->hip_priv) - return; - - sdev = container_of(hip, struct slsi_dev, hip4_inst); - if (!sdev || !sdev->service) - return; - - if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED) - return; - - service = sdev->service; - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - - if (conf_hip4_ver == 4) { - for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++) - if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ) - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]); - } else { - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); - } -#else - scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost); -#endif - - slsi_log_client_msg(sdev, UDI_DRV_RESUME_IND, 0, NULL); - SCSC_HIP4_SAMPLER_RESUME(hip->hip_priv->minor); - atomic_set(&hip->hip_priv->in_suspend, 0); -} - -void hip4_freeze(struct slsi_hip4 *hip) -{ - struct slsi_dev *sdev; - struct scsc_service *service; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; -#endif - - if (!hip || !hip->hip_priv) - return; - - sdev = container_of(hip, struct slsi_dev, hip4_inst); - if (!sdev || !sdev->service) - return; - - if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED) - return; - - service = sdev->service; - - closing = ktime_get(); - atomic_set(&hip->hip_priv->closing, 1); - - hip4_dump_dbg(hip, NULL, NULL, service); -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - - if (conf_hip4_ver == 4) { - for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++) - if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ) - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[i]); - - tasklet_kill(&hip->hip_priv->intr_tasklet); - cancel_work_sync(&hip->hip_priv->intr_wq_ctrl); - cancel_work_sync(&hip->hip_priv->intr_wq_fb); - } else { - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost); - cancel_work_sync(&hip->hip_priv->intr_wq); - } -#else - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost); - cancel_work_sync(&hip->hip_priv->intr_wq); -#endif - flush_workqueue(hip->hip_priv->hip4_workq); - destroy_workqueue(hip->hip_priv->hip4_workq); - atomic_set(&hip->hip_priv->watchdog_timer_active, 0); - - /* Deactive the wd timer prior its expiration */ - del_timer_sync(&hip->hip_priv->watchdog); -} - -void hip4_deinit(struct slsi_hip4 *hip) -{ - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - struct scsc_service *service; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; -#endif - if (!sdev || !sdev->service) - return; - - service = sdev->service; - -#ifdef CONFIG_SCSC_LOGRING - slsi_traffic_mon_client_unregister(sdev, hip->hip_priv); - /* Reenable logring in case was disabled */ - scsc_logring_enable(true); -#endif -#ifdef CONFIG_SCSC_QOS - /* de-register with traffic monitor */ - slsi_traffic_mon_client_unregister(sdev, hip); - scsc_service_pm_qos_remove_request(service); -#endif - -#ifdef CONFIG_SCSC_SMAPPER - /* Init SMAPPER */ - if (hip4_smapper_is_enabled) { - hip4_smapper_is_enabled = false; - hip4_smapper_deinit(sdev, hip); - } -#endif - - closing = ktime_get(); - atomic_set(&hip->hip_priv->closing, 1); - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++) - if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ) - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[i]); - - tasklet_kill(&hip->hip_priv->intr_tasklet); - cancel_work_sync(&hip->hip_priv->intr_wq_ctrl); - cancel_work_sync(&hip->hip_priv->intr_wq_fb); - - for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) - if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ) - scsc_service_mifintrbit_unregister_tohost(service, hip->hip_priv->intr_tohost_mul[i]); - - /* Get the Version reported by the FW */ - conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init); - - if (conf_hip4_ver == 4) { - netif_napi_del(&hip->hip_priv->napi); - } -#endif - scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost); - cancel_work_sync(&hip->hip_priv->intr_wq); - scsc_service_mifintrbit_unregister_tohost(service, hip->hip_priv->intr_tohost); - - flush_workqueue(hip->hip_priv->hip4_workq); - destroy_workqueue(hip->hip_priv->hip4_workq); - - scsc_service_mifintrbit_free_fromhost(service, hip->hip_priv->intr_fromhost, SCSC_MIFINTR_TARGET_R4); - -#ifdef CONFIG_ANDROID -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - wake_lock_destroy(&hip->hip_priv->hip4_wake_lock_tx); - wake_lock_destroy(&hip->hip_priv->hip4_wake_lock_ctrl); - wake_lock_destroy(&hip->hip_priv->hip4_wake_lock_data); -#endif - wake_lock_destroy(&hip->hip_priv->hip4_wake_lock); -#endif - - /* If we get to that point with rx_lock/tx_lock claimed, trigger BUG() */ - WARN_ON(atomic_read(&hip->hip_priv->in_tx)); - WARN_ON(atomic_read(&hip->hip_priv->in_rx)); - - atomic_set(&hip->hip_priv->watchdog_timer_active, 0); - /* Deactive the wd timer prior its expiration */ - del_timer_sync(&hip->hip_priv->watchdog); - -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (hip->hip_priv->stats.procfs_dir) { - remove_proc_entry("driver/hip4/jitter", NULL); - remove_proc_entry("driver/hip4/info", NULL); - remove_proc_entry("driver/hip4/history", NULL); - remove_proc_entry("driver/hip4", NULL); - } -#endif - kfree(hip->hip_priv); - - hip->hip_priv = NULL; -} diff --git a/drivers/net/wireless/scsc/hip4.h b/drivers/net/wireless/scsc/hip4.h deleted file mode 100755 index bed0b1fd646f..000000000000 --- a/drivers/net/wireless/scsc/hip4.h +++ /dev/null @@ -1,386 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __HIP4_H__ -#define __HIP4_H__ - -/** - * This header file is the public HIP4 interface, which will be accessible by - * Wi-Fi service driver components. - * - * All struct and internal HIP functions shall be moved to a private header - * file. - */ - -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_SCSC_WLAN_RX_NAPI -#include -#endif -#ifndef SLSI_TEST_DEV -#ifdef CONFIG_ANDROID -#include -#endif -#endif -#include "mbulk.h" -#ifdef CONFIG_SCSC_SMAPPER -#include "hip4_smapper.h" -#endif - -/* Shared memory Layout - * - * |-------------------------| CONFIG - * | CONFIG + Queues | - * | --------- | - * | MIB | - * |-------------------------| TX Pool - * | TX DAT | - * | --------- | - * | TX CTL | - * |-------------------------| RX Pool - * | RX | - * |-------------------------| - */ - -/**** OFFSET SHOULD BE 4096 BYTES ALIGNED ***/ -/*** CONFIG POOL ***/ -#define HIP4_WLAN_CONFIG_OFFSET 0x00000 -#define HIP4_WLAN_CONFIG_SIZE 0x02000 /* 8 kB*/ -/*** MIB POOL ***/ -#define HIP4_WLAN_MIB_OFFSET (HIP4_WLAN_CONFIG_OFFSET + HIP4_WLAN_CONFIG_SIZE) -#define HIP4_WLAN_MIB_SIZE 0x08000 /* 32 kB*/ -/*** TX POOL ***/ -#define HIP4_WLAN_TX_OFFSET (HIP4_WLAN_MIB_OFFSET + HIP4_WLAN_MIB_SIZE) -/*** TX POOL - DAT POOL ***/ -#define HIP4_WLAN_TX_DAT_OFFSET HIP4_WLAN_TX_OFFSET -#define HIP4_WLAN_TX_DAT_SIZE 0xe6000 /* 920 kB*/ -/*** TX POOL - CTL POOL ***/ -#define HIP4_WLAN_TX_CTL_OFFSET (HIP4_WLAN_TX_DAT_OFFSET + HIP4_WLAN_TX_DAT_SIZE) -#define HIP4_WLAN_TX_CTL_SIZE 0x10000 /* 64 kB*/ -#define HIP4_WLAN_TX_SIZE (HIP4_WLAN_TX_DAT_SIZE + HIP4_WLAN_TX_CTL_SIZE) -/*** RX POOL ***/ -#define HIP4_WLAN_RX_OFFSET (HIP4_WLAN_TX_CTL_OFFSET + HIP4_WLAN_TX_CTL_SIZE) -#ifdef CONFIG_SCSC_PCIE -#define HIP4_WLAN_RX_SIZE 0x80000 /* 512 kB */ -#else -#define HIP4_WLAN_RX_SIZE 0x100000 /* 1MB */ -#endif -/*** TOTAL : CONFIG POOL + TX POOL + RX POOL ***/ -#define HIP4_WLAN_TOTAL_MEM (HIP4_WLAN_CONFIG_SIZE + HIP4_WLAN_MIB_SIZE + \ - HIP4_WLAN_TX_SIZE + HIP4_WLAN_RX_SIZE) /* 2 MB */ - -#define HIP4_POLLING_MAX_PACKETS 512 - -#define HIP4_DAT_MBULK_SIZE (2 * 1024) -#define HIP4_DAT_SLOTS (HIP4_WLAN_TX_DAT_SIZE / HIP4_DAT_MBULK_SIZE) -#define HIP4_CTL_MBULK_SIZE (2 * 1024) -#define HIP4_CTL_SLOTS (HIP4_WLAN_TX_CTL_SIZE / HIP4_CTL_MBULK_SIZE) - -#define MIF_HIP_CFG_Q_NUM 6 - -#define MIF_NO_IRQ 0xff - -/* Current versions supported by this HIP */ -#define HIP4_SUPPORTED_V1 3 -#define HIP4_SUPPORTED_V2 4 - -enum hip4_hip_q_conf { - HIP4_MIF_Q_FH_CTRL, - HIP4_MIF_Q_FH_DAT, - HIP4_MIF_Q_FH_RFB, - HIP4_MIF_Q_TH_CTRL, - HIP4_MIF_Q_TH_DAT, - HIP4_MIF_Q_TH_RFB -}; - -struct hip4_hip_config_version_4 { - /* Host owned */ - u32 magic_number; /* 0xcaba0401 */ - u16 hip_config_ver; /* Version of this configuration structure = 2*/ - u16 config_len; /* Size of this configuration structure */ - - /* FW owned */ - u32 compat_flag; /* flag of the expected driver's behaviours */ - - u16 sap_mlme_ver; /* Fapi SAP_MLME version*/ - u16 sap_ma_ver; /* Fapi SAP_MA version */ - u16 sap_debug_ver; /* Fapi SAP_DEBUG version */ - u16 sap_test_ver; /* Fapi SAP_TEST version */ - - u32 fw_build_id; /* Firmware Build Id */ - u32 fw_patch_id; /* Firmware Patch Id */ - - u8 unidat_req_headroom; /* Headroom the host shall reserve in mbulk for MA-UNITDATA.REQ signal */ - u8 unidat_req_tailroom; /* Tailroom the host shall reserve in mbulk for MA-UNITDATA.REQ signal */ - u8 bulk_buffer_align; /* 4 */ - - /* Host owned */ - u8 host_cache_line; /* 64 */ - - u32 host_buf_loc; /* location of the host buffer in MIF_ADDR */ - u32 host_buf_sz; /* in byte, size of the host buffer */ - u32 fw_buf_loc; /* location of the firmware buffer in MIF_ADDR */ - u32 fw_buf_sz; /* in byte, size of the firmware buffer */ - u32 mib_loc; /* MIB location in MIF_ADDR */ - u32 mib_sz; /* MIB size */ - u32 log_config_loc; /* Logging Configuration Location in MIF_ADDR */ - u32 log_config_sz; /* Logging Configuration Size in MIF_ADDR */ - - u8 mif_fh_int_n; /* MIF from-host interrupt bit position for all HIP queue */ - u8 reserved1[3]; - - u8 mif_th_int_n[6]; /* MIF to-host interrupt bit positions for each HIP queue */ - u8 reserved2[2]; - - u32 scbrd_loc; /* Scoreboard locatin in MIF_ADDR */ - - u16 q_num; /* 6 */ - u16 q_len; /* 256 */ - u16 q_idx_sz; /* 1 */ - u8 reserved3[2]; - - u32 q_loc[MIF_HIP_CFG_Q_NUM]; - -#ifdef CONFIG_SCSC_SMAPPER - u8 smapper_th_req; /* TH smapper request interrupt bit position */ - u8 smapper_fh_ind; /* FH smapper ind interrupt bit position */ - u8 smapper_mbox_scb; /* SMAPPER MBOX scoreboard location */ - u8 smapper_entries_banks[16]; /* num entries banks */ - u8 smapper_pow_sz[16]; /* Power of size of entry i.e. 12 = 4096B */ - u32 smapper_bank_addr[16]; /* Bank start addr */ -#else - u8 reserved_nosmapper[99]; -#endif - u8 reserved4[16]; -} __packed; - -struct hip4_hip_config_version_5 { - /* Host owned */ - u32 magic_number; /* 0xcaba0401 */ - u16 hip_config_ver; /* Version of this configuration structure = 2*/ - u16 config_len; /* Size of this configuration structure */ - - /* FW owned */ - u32 compat_flag; /* flag of the expected driver's behaviours */ - - u16 sap_mlme_ver; /* Fapi SAP_MLME version*/ - u16 sap_ma_ver; /* Fapi SAP_MA version */ - u16 sap_debug_ver; /* Fapi SAP_DEBUG version */ - u16 sap_test_ver; /* Fapi SAP_TEST version */ - - u32 fw_build_id; /* Firmware Build Id */ - u32 fw_patch_id; /* Firmware Patch Id */ - - u8 unidat_req_headroom; /* Headroom the host shall reserve in mbulk for MA-UNITDATA.REQ signal */ - u8 unidat_req_tailroom; /* Tailroom the host shall reserve in mbulk for MA-UNITDATA.REQ signal */ - u8 bulk_buffer_align; /* 4 */ - - /* Host owned */ - u8 host_cache_line; /* 64 */ - - u32 host_buf_loc; /* location of the host buffer in MIF_ADDR */ - u32 host_buf_sz; /* in byte, size of the host buffer */ - u32 fw_buf_loc; /* location of the firmware buffer in MIF_ADDR */ - u32 fw_buf_sz; /* in byte, size of the firmware buffer */ - u32 mib_loc; /* MIB location in MIF_ADDR */ - u32 mib_sz; /* MIB size */ - u32 log_config_loc; /* Logging Configuration Location in MIF_ADDR */ - u32 log_config_sz; /* Logging Configuration Size in MIF_ADDR */ - - u8 mif_fh_int_n; /* MIF from-host interrupt bit position */ - u8 mif_th_int_n; /* MIF to-host interrpt bit position */ - u8 reserved[2]; - - u32 scbrd_loc; /* Scoreboard locatin in MIF_ADDR */ - - u16 q_num; /* 6 */ - u16 q_len; /* 256 */ - u16 q_idx_sz; /* 1 */ - u8 reserved2[2]; - - u32 q_loc[MIF_HIP_CFG_Q_NUM]; - - u8 reserved3[16]; -} __packed; - -struct hip4_hip_init { - /* Host owned */ - u32 magic_number; /* 0xcaaa0400 */ - /* FW owned */ - u32 conf_hip4_ver; - /* Host owned */ - u32 version_a_ref; /* Location of Config structure A (old) */ - u32 version_b_ref; /* Location of Config structure B (new) */ -} __packed; - -#define MAX_NUM 256 -struct hip4_hip_q { - u32 array[MAX_NUM]; - u8 idx_read; /* To keep track */ - u8 idx_write; /* To keep track */ - u8 total; -} __aligned(64); - -struct hip4_hip_control { - struct hip4_hip_init init; - struct hip4_hip_config_version_5 config_v5 __aligned(32); - struct hip4_hip_config_version_4 config_v4 __aligned(32); - u32 scoreboard[256] __aligned(64); - struct hip4_hip_q q[MIF_HIP_CFG_Q_NUM] __aligned(64); -} __aligned(4096); - -struct slsi_hip4; - -/* This struct is private to the HIP implementation */ -struct hip4_priv { -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - struct tasklet_struct intr_tasklet; - struct work_struct intr_wq_ctrl; - struct work_struct intr_wq_fb; - struct napi_struct napi; -#endif - struct work_struct intr_wq; - - /* Interrupts cache < v4 */ - /* TOHOST */ - u32 intr_tohost; - - /* Interrupts cache v4 */ - u32 intr_tohost_mul[MIF_HIP_CFG_Q_NUM]; - /* FROMHOST */ - u32 intr_fromhost; - - /* For workqueue */ - struct slsi_hip4 *hip; - - /* Pool for data frames*/ - u8 host_pool_id_dat; - /* Pool for ctl frames*/ - u8 host_pool_id_ctl; - - /* rx cycle lock */ - spinlock_t rx_lock; - /* tx cycle lock */ - spinlock_t tx_lock; - - /* Scoreboard update spinlock */ - rwlock_t rw_scoreboard; - - /* Watchdog timer */ - struct timer_list watchdog; - /* wd spinlock */ - spinlock_t watchdog_lock; - /* wd timer control */ - atomic_t watchdog_timer_active; -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - DECLARE_BITMAP(irq_bitmap, MIF_HIP_CFG_Q_NUM); -#endif - -#if !defined SLSI_TEST_DEV && defined CONFIG_ANDROID -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - struct wake_lock hip4_wake_lock_tx; - struct wake_lock hip4_wake_lock_ctrl; - struct wake_lock hip4_wake_lock_data; -#endif - /* Wakelock for modem_ctl */ - struct wake_lock hip4_wake_lock; -#endif - - /* Control the hip4 deinit */ - atomic_t closing; - atomic_t in_tx; - atomic_t in_rx; - atomic_t in_suspend; - u32 storm_count; - - struct { - atomic_t irqs; - atomic_t spurious_irqs; - u32 q_num_frames[MIF_HIP_CFG_Q_NUM]; - ktime_t start; - struct proc_dir_entry *procfs_dir; - } stats; - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - /*minor*/ - u32 minor; -#endif - u8 unidat_req_headroom; /* Headroom the host shall reserve in mbulk for MA-UNITDATA.REQ signal */ - u8 unidat_req_tailroom; /* Tailroom the host shall reserve in mbulk for MA-UNITDATA.REQ signal */ - u32 version; /* Version of the running FW */ - void *scbrd_base; /* Scbrd_base pointer */ - - /* Global domain Q control*/ - atomic_t gactive; - atomic_t gmod; - atomic_t gcod; - int saturated; - int guard; - /* Global domain Q spinlock */ - spinlock_t gbot_lock; - -#ifdef CONFIG_SCSC_SMAPPER - /* SMAPPER */ - /* Leman has 4 Banks of 160 entries each and 4 Banks of 64 entries each. Each Tx stream is - * expected to use 2 Bank . In RSDB, 5GHz streams require higher throughput - * so the bigger banks are allocated for 5GHz streams and the - * smaller banks are for 2.4GHz streams - */ - struct hip4_smapper_bank smapper_banks[HIP4_SMAPPER_TOTAL_BANKS]; - struct hip4_smapper_control smapper_control; -#endif -#ifdef CONFIG_SCSC_QOS - /* PM QoS control */ - struct work_struct pm_qos_work; - /* PM QoS control spinlock */ - spinlock_t pm_qos_lock; - u8 pm_qos_state; -#endif - /* Collection artificats */ - void *mib_collect; - u16 mib_sz; - /* Mutex to protect hcf file collection if a tear down is triggered */ - struct mutex in_collection; - - struct workqueue_struct *hip4_workq; -}; - -struct scsc_service; - -struct slsi_hip4 { - struct hip4_priv *hip_priv; - struct hip4_hip_control *hip_control; - scsc_mifram_ref hip_ref; -}; - -/* Public functions */ -int hip4_init(struct slsi_hip4 *hip); -int hip4_setup(struct slsi_hip4 *hip); -void hip4_suspend(struct slsi_hip4 *hip); -void hip4_resume(struct slsi_hip4 *hip); -void hip4_freeze(struct slsi_hip4 *hip); -void hip4_deinit(struct slsi_hip4 *hip); -int hip4_free_ctrl_slots_count(struct slsi_hip4 *hip); - -int scsc_wifi_transmit_frame(struct slsi_hip4 *hip, bool ctrl_packet, struct sk_buff *skb); - -/* Macros for accessing information stored in the hip_config struct */ -#define scsc_wifi_get_hip_config_version_4_u8(buff_ptr, member) le16_to_cpu((((struct hip4_hip_config_version_4 *)(buff_ptr))->member)) -#define scsc_wifi_get_hip_config_version_4_u16(buff_ptr, member) le16_to_cpu((((struct hip4_hip_config_version_4 *)(buff_ptr))->member)) -#define scsc_wifi_get_hip_config_version_4_u32(buff_ptr, member) le32_to_cpu((((struct hip4_hip_config_version_4 *)(buff_ptr))->member)) -#define scsc_wifi_get_hip_config_version_5_u8(buff_ptr, member) le16_to_cpu((((struct hip4_hip_config_version_5 *)(buff_ptr))->member)) -#define scsc_wifi_get_hip_config_version_5_u16(buff_ptr, member) le16_to_cpu((((struct hip4_hip_config_version_5 *)(buff_ptr))->member)) -#define scsc_wifi_get_hip_config_version_5_u32(buff_ptr, member) le32_to_cpu((((struct hip4_hip_config_version_5 *)(buff_ptr))->member)) -#define scsc_wifi_get_hip_config_u8(buff_ptr, member, ver) le16_to_cpu((((struct hip4_hip_config_version_##ver *)(buff_ptr->config_v##ver))->member)) -#define scsc_wifi_get_hip_config_u16(buff_ptr, member, ver) le16_to_cpu((((struct hip4_hip_config_version_##ver *)(buff_ptr->config_v##ver))->member)) -#define scsc_wifi_get_hip_config_u32(buff_ptr, member, ver) le32_to_cpu((((struct hip4_hip_config_version_##ver *)(buff_ptr->config_v##ver))->member)) -#define scsc_wifi_get_hip_config_version(buff_ptr) le32_to_cpu((((struct hip4_hip_init *)(buff_ptr))->conf_hip4_ver)) - -#endif diff --git a/drivers/net/wireless/scsc/hip4_sampler.c b/drivers/net/wireless/scsc/hip4_sampler.c deleted file mode 100755 index cfe215b691c7..000000000000 --- a/drivers/net/wireless/scsc/hip4_sampler.c +++ /dev/null @@ -1,945 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif -#include -#include -#include "hip4_sampler.h" - -#include "debug.h" - -struct hip4_record { - u32 record_num; - ktime_t ts; - u32 record; - u32 record2; -} __packed; - -static atomic_t in_read; - -/* Create a global spinlock for all the instances */ -/* It is less efficent, but we simplify the implementation */ -static spinlock_t g_spinlock; - -static bool hip4_sampler_enable = true; -module_param(hip4_sampler_enable, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_enable, "Enable hip4_sampler_enable. Run-time option - (default: Y)"); - -static bool hip4_sampler_dynamic = true; -module_param(hip4_sampler_dynamic, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_dynamic, "Enable hip4_sampler dynamic adaptation based on TPUT. Run-time option - (default: Y)"); - -static int hip4_sampler_kfifo_len = 128 * 1024; -module_param(hip4_sampler_kfifo_len, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_kfifo_len, "Streaming fifo buffer length in num of records- default: 262144 Max: 262144. Loaded at /dev open"); - -static int hip4_sampler_static_kfifo_len = 128 * 1024; -module_param(hip4_sampler_static_kfifo_len, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_static_kfifo_len, "Offline fifo buffer length in num of records- default: 262144 Max: 262144. Loaded at /dev open"); - -bool hip4_sampler_sample_q = true; -module_param(hip4_sampler_sample_q, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_q, "Sample Queues. Default: Y. Run time option"); - -bool hip4_sampler_sample_qref = true; -module_param(hip4_sampler_sample_qref, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_qref, "Sample Queue References. Default: Y. Run time option"); - -bool hip4_sampler_sample_int = true; -module_param(hip4_sampler_sample_int, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_int, "Sample WQ/Tasklet Intr BH in/out. Default: Y. Run time option"); - -bool hip4_sampler_sample_fapi = true; -module_param(hip4_sampler_sample_fapi, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_fapi, "Sample FAPI ctrl signals. Default: Y. Run time option"); - -bool hip4_sampler_sample_through = true; -module_param(hip4_sampler_sample_through, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_through, "Sample throughput. Default: Y. Run time option"); - -bool hip4_sampler_sample_tcp = true; -module_param(hip4_sampler_sample_tcp, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_tcp, "Sample TCP streams. Default: Y. Run time option"); - -bool hip4_sampler_sample_start_stop_q = true; -module_param(hip4_sampler_sample_start_stop_q, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_start_stop_q, "Sample Stop/Start queues. Default: Y. Run time option"); - -bool hip4_sampler_sample_mbulk = true; -module_param(hip4_sampler_sample_mbulk, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_mbulk, "Sample Mbulk counter. Default: Y. Run time option"); - -bool hip4_sampler_sample_qfull; -module_param(hip4_sampler_sample_qfull, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_qfull, "Sample Q full event. Default: N. Run time option"); - -bool hip4_sampler_sample_mfull = true; -module_param(hip4_sampler_sample_mfull, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_sample_mfull, "Sample Mbulk full event. Default: Y. Run time option"); - -bool hip4_sampler_vif = true; -module_param(hip4_sampler_vif, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_vif, "Sample VIF. Default: Y. Run time option"); - -bool hip4_sampler_bot = true; -module_param(hip4_sampler_bot, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_bot, "Sample BOT. Default: Y. Run time option"); - -bool hip4_sampler_pkt_tx = true; -module_param(hip4_sampler_pkt_tx, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_pkt_tx, "Track TX Data packet TX->HIP4->FB. Default: Y. Run time option"); - -bool hip4_sampler_suspend_resume = true; -module_param(hip4_sampler_suspend_resume, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hip4_sampler_suspend_resume, "Sample Suspend/Resume events. Default: Y. Run time option"); - -#define HIP4_TPUT_HLIMIT 400000000 /* 400Mbps */ -#define HIP4_TPUT_LLIMIT 350000000 /* 350Mbps */ -#define HIP4_TPUT_HSECONDS 1 -#define HIP4_TPUT_LSECONDS 5 - -static bool hip4_sampler_sample_q_hput; -static bool hip4_sampler_sample_qref_hput; -static bool hip4_sampler_sample_int_hput; -static bool hip4_sampler_sample_fapi_hput; -/* static bool hip4_sampler_sample_through_hput; */ -/* static bool hip4_sampler_sample_start_stop_q_hput; */ -/* static bool hip4_sampler_sample_mbulk_hput; */ -/* static bool hip4_sampler_sample_qfull_hput; */ -/* static bool hip4_sampler_sample_mfull_hput; */ -static bool hip4_sampler_vif_hput; -static bool hip4_sampler_bot_hput; -static bool hip4_sampler_pkt_tx_hput; -static bool hip4_sampler_suspend_resume_hput; - -static bool hip4_sampler_in_htput; -static u16 hip4_sampler_in_htput_seconds; - -#define DRV_NAME "hip4_sampler" -#define DEVICE_NAME "hip4_sampler" - -#ifndef VM_RESERVED -#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) -#endif - -#define VER_MAJOR 0 -#define VER_MINOR 0 - -DECLARE_BITMAP(bitmap_hip4_sampler_minor, SCSC_HIP4_DEBUG_INTERFACES); - -enum hip4_dg_errors { - NO_ERROR = 0, - BUFFER_OVERFLOW, - KFIFO_ERROR, - KFIFO_FULL, -}; - -enum hip4_type { - STREAMING = 0, - OFFLINE, -}; - -struct hip4_sampler_dev { - /* file pointer */ - struct file *filp; - /* char device */ - struct cdev cdev; - /*device pointer*/ - struct device *dev; - /*mx pointer*/ - struct scsc_mx *mx; - /* Associated kfifo */ - DECLARE_KFIFO_PTR(fifo, struct hip4_record); - /* Associated read_wait queue.*/ - wait_queue_head_t read_wait; - /* Device in error */ - enum hip4_dg_errors error; - /* Device node mutex for fops */ - struct mutex mutex; - /* Record number */ - u32 record_num; - /* To profile kfifo num elements */ - u32 kfifo_max; - /* Sampler type streaming/offline */ - enum hip4_type type; - /* reference to minor number */ - u32 minor; -}; - -/** - * SCSC User Space debug sampler interface (singleton) - */ -static struct { - bool init; - dev_t device; - struct class *class_hip4_sampler; - struct hip4_sampler_dev devs[SCSC_HIP4_DEBUG_INTERFACES]; -} hip4_sampler; - -void __hip4_sampler_update_record(struct hip4_sampler_dev *hip4_dev, u32 minor, u8 param1, u8 param2, u8 param3, u8 param4, u32 param5) -{ - struct hip4_record ev; - u32 ret; - u32 cpu; - u32 freq = 0; - - /* If char device if open, use streaming buffer */ - if (hip4_dev->filp) { - /* put string into the Streaming fifo */ - if (kfifo_avail(&hip4_dev->fifo)) { - /* Push values in Fifo*/ - cpu = smp_processor_id(); - if (hip4_dev->record_num % 64 == 0) - freq = (cpufreq_quick_get(cpu) / 1000) & 0xfff; - ev.record_num = (0x0000ffff & hip4_dev->record_num++) | (cpu << 28) | (freq << 16); - ev.ts = ktime_get(); - ev.record = ((param1 & 0xff) << 24) | ((param2 & 0xff) << 16) | ((param3 & 0xff) << 8) | (param4 & 0xff); - ev.record2 = param5; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) - kfifo_put(&hip4_dev->fifo, ev); -#else - kfifo_put(&hip4_dev->fifo, &ev); -#endif - ret = kfifo_len(&hip4_dev->fifo); - if (ret > hip4_dev->kfifo_max) - hip4_dev->kfifo_max = ret; - } else { - hip4_dev->error = KFIFO_FULL; - return; - } - wake_up_interruptible(&hip4_dev->read_wait); - /* If streaming buffer is not in use, put samples in offline buffer */ - } else { - /* Get associated Offline buffer */ - hip4_dev = &hip4_sampler.devs[minor + 1]; - /* Record in offline fifo */ - /* if fifo is full, remove last item */ - if (kfifo_is_full(&hip4_dev->fifo)) - ret = kfifo_get(&hip4_dev->fifo, &ev); - cpu = smp_processor_id(); - if (hip4_dev->record_num % 64 == 0) - freq = (cpufreq_quick_get(cpu) / 1000) & 0xfff; - /* Push values in Static Fifo*/ - ev.record_num = (0x0000ffff & hip4_dev->record_num++) | (cpu << 28) | (freq << 16); - ev.ts = ktime_get(); - ev.record = ((param1 & 0xff) << 24) | ((param2 & 0xff) << 16) | ((param3 & 0xff) << 8) | (param4 & 0xff); - ev.record2 = param5; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) - kfifo_put(&hip4_dev->fifo, ev); -#else - kfifo_put(&hip4_dev->fifo, &ev); -#endif - } -} - -void hip4_sampler_update_record(u32 minor, u8 param1, u8 param2, u8 param3, u8 param4, u32 param5) -{ - struct hip4_sampler_dev *hip4_dev; - unsigned long flags; - - if (!hip4_sampler_enable || !hip4_sampler.init) - return; - - if (atomic_read(&in_read)) - return; - - if (minor >= SCSC_HIP4_INTERFACES) - return; - - spin_lock_irqsave(&g_spinlock, flags); - hip4_dev = &hip4_sampler.devs[minor]; - __hip4_sampler_update_record(hip4_dev, minor, param1, param2, param3, param4, param5); - spin_unlock_irqrestore(&g_spinlock, flags); -} - -static void hip4_sampler_store_param(void) -{ - hip4_sampler_sample_q_hput = hip4_sampler_sample_q; - hip4_sampler_sample_qref_hput = hip4_sampler_sample_qref; - hip4_sampler_sample_int_hput = hip4_sampler_sample_int; - hip4_sampler_sample_fapi_hput = hip4_sampler_sample_fapi; - /* hip4_sampler_sample_through_hput = hip4_sampler_sample_through; */ - /* hip4_sampler_sample_start_stop_q_hput = hip4_sampler_sample_start_stop_q; */ - /* hip4_sampler_sample_mbulk_hput = hip4_sampler_sample_mbulk; */ - /* hip4_sampler_sample_qfull_hput = hip4_sampler_sample_qfull; */ - /* hip4_sampler_sample_mfull_hput = hip4_sampler_sample_mfull; */ - hip4_sampler_vif_hput = hip4_sampler_vif; - hip4_sampler_bot_hput = hip4_sampler_bot; - hip4_sampler_pkt_tx_hput = hip4_sampler_pkt_tx; - hip4_sampler_suspend_resume_hput = hip4_sampler_suspend_resume; - - /* Reset values to avoid contention */ - hip4_sampler_sample_q = false; - hip4_sampler_sample_qref = false; - hip4_sampler_sample_int = false; - hip4_sampler_sample_fapi = false; - /* hip4_sampler_sample_through_hput = false; */ - /* hip4_sampler_sample_start_stop_q_hput = false; */ - /* hip4_sampler_sample_mbulk = false; */ - /* hip4_sampler_sample_qfull_hput = false; */ - /* hip4_sampler_sample_mfull_hput = false; */ - hip4_sampler_vif = false; - hip4_sampler_bot = false; - hip4_sampler_pkt_tx = false; - hip4_sampler_suspend_resume = false; -} - -static void hip4_sampler_restore_param(void) -{ - hip4_sampler_sample_q = hip4_sampler_sample_q_hput; - hip4_sampler_sample_qref = hip4_sampler_sample_qref_hput; - hip4_sampler_sample_int = hip4_sampler_sample_int_hput; - hip4_sampler_sample_fapi = hip4_sampler_sample_fapi_hput; - /* hip4_sampler_sample_through = hip4_sampler_sample_through_hput; */ - /* hip4_sampler_sample_start_stop_q = hip4_sampler_sample_start_stop_q_hput; */ - /* hip4_sampler_sample_mbulk = hip4_sampler_sample_mbulk_hput; */ - /* hip4_sampler_sample_qfull = hip4_sampler_sample_qfull_hput; */ - /* hip4_sampler_sample_mfull = hip4_sampler_sample_mfull_hput; */ - hip4_sampler_vif = hip4_sampler_vif_hput; - hip4_sampler_bot = hip4_sampler_bot_hput; - hip4_sampler_pkt_tx = hip4_sampler_pkt_tx_hput; - hip4_sampler_suspend_resume = hip4_sampler_suspend_resume_hput; -} - -static void hip4_sampler_dynamic_switcher(u32 bps) -{ - /* Running in htput, */ - if (hip4_sampler_in_htput) { - if (bps < HIP4_TPUT_LLIMIT) { - /* bps went down , count number of times to switch */ - hip4_sampler_in_htput_seconds++; - if (hip4_sampler_in_htput_seconds >= HIP4_TPUT_LSECONDS) { - /* HIP4_TPUT_LSECONDS have passed, switch to low tput samples */ - hip4_sampler_in_htput = false; - hip4_sampler_in_htput_seconds = 0; - hip4_sampler_restore_param(); - } - } else { - hip4_sampler_in_htput_seconds = 0; - } - } else { - if (bps > HIP4_TPUT_HLIMIT) { - /* bps went up, count number of times to switch */ - hip4_sampler_in_htput_seconds++; - if (hip4_sampler_in_htput_seconds >= HIP4_TPUT_HSECONDS) { - /* HIP4_TPUT_LSECONDS have passed, switch to high tput samples */ - hip4_sampler_in_htput = true; - hip4_sampler_in_htput_seconds = 0; - hip4_sampler_store_param(); - } - } else { - hip4_sampler_in_htput_seconds = 0; - } - } -} - -static u32 g_tput_rx; -static u32 g_tput_tx; - -void hip4_sampler_tput_monitor(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx) -{ - struct hip4_sampler_dev *hip4_sampler_dev = (struct hip4_sampler_dev *)client_ctx; - - if (!hip4_sampler_enable) - return; - - if ((g_tput_tx == tput_tx) && (g_tput_rx == tput_rx)) - return; - - g_tput_tx = tput_tx; - g_tput_rx = tput_rx; - - if (hip4_sampler_dynamic) { - /* Call the dynamic switcher with the computed bps - * The algorithm will decide to not change, decrease - * or increase the sampler verbosity - */ - if (tput_rx > tput_tx) - hip4_sampler_dynamic_switcher(tput_rx); - else - hip4_sampler_dynamic_switcher(tput_tx); - } - - /* Generate the TX sample, in bps, Kbps, or Mbps */ - if (tput_tx < 1000) { - SCSC_HIP4_SAMPLER_THROUG(hip4_sampler_dev->minor, 1, (tput_tx & 0xff00) >> 8, tput_tx & 0xff); - } else if ((tput_tx >= 1000) && (tput_tx < (1000 * 1000))) { - tput_tx = tput_tx / 1000; - SCSC_HIP4_SAMPLER_THROUG_K(hip4_sampler_dev->minor, 1, (tput_tx & 0xff00) >> 8, tput_tx & 0xff); - } else { - tput_tx = tput_tx / (1000 * 1000); - SCSC_HIP4_SAMPLER_THROUG_M(hip4_sampler_dev->minor, 1, (tput_tx & 0xff00) >> 8, tput_tx & 0xff); - } - - /* Generate the RX sample, in bps, Kbps, or Mbps */ - if (tput_rx < 1000) { - SCSC_HIP4_SAMPLER_THROUG(hip4_sampler_dev->minor, 0, (tput_rx & 0xff00) >> 8, tput_rx & 0xff); - } else if ((tput_rx >= 1000) && (tput_rx < (1000 * 1000))) { - tput_rx = tput_rx / 1000; - SCSC_HIP4_SAMPLER_THROUG_K(hip4_sampler_dev->minor, 0, (tput_rx & 0xff00) >> 8, tput_rx & 0xff); - } else { - tput_rx = tput_rx / (1000 * 1000); - SCSC_HIP4_SAMPLER_THROUG_M(hip4_sampler_dev->minor, 0, (tput_rx & 0xff00) >> 8, tput_rx & 0xff); - } -} - -void hip4_sampler_tcp_decode(struct slsi_dev *sdev, struct net_device *dev, u8 *frame, bool from_ba) -{ - struct tcphdr *tcp_hdr; - struct ethhdr *ehdr = (struct ethhdr *)(frame); - struct netdev_vif *ndev_vif = netdev_priv(dev); - u8 *ip_frame; - u16 ip_data_offset; - u8 hlen; - u16 len; - u8 proto; - u8 idx; - - if (be16_to_cpu(ehdr->h_proto) != ETH_P_IP) - return; - - ip_frame = frame + ETH_HLEN; - proto = ip_frame[9]; - - if (proto != IPPROTO_TCP) - return; - - ip_data_offset = 20; - hlen = ip_frame[0] & 0x0F; - len = ip_frame[2] << 8 | ip_frame[3]; - - if (hlen > 5) - ip_data_offset += (hlen - 5) * 4; - - tcp_hdr = (struct tcphdr *)(ip_frame + ip_data_offset); - - /* Search for an existing record on this connection. */ - for (idx = 0; idx < TCP_ACK_SUPPRESSION_RECORDS_MAX; idx++) { - struct slsi_tcp_ack_s *tcp_ack; - u32 rwnd = 0; - - tcp_ack = &ndev_vif->ack_suppression[idx]; - slsi_spinlock_lock(&tcp_ack->lock); - if ((tcp_ack->dport == tcp_hdr->source) && (tcp_ack->sport == tcp_hdr->dest)) { - if (from_ba && tcp_hdr->syn && tcp_hdr->ack) { - unsigned char *options; - u32 optlen = 0, len = 0; - - if (tcp_hdr->doff > 5) - optlen = (tcp_hdr->doff - 5) * 4; - - options = (u8 *)tcp_hdr + TCP_ACK_SUPPRESSION_OPTIONS_OFFSET; - - while (optlen > 0) { - switch (options[0]) { - case TCP_ACK_SUPPRESSION_OPTION_EOL: - len = 1; - break; - case TCP_ACK_SUPPRESSION_OPTION_NOP: - len = 1; - break; - case TCP_ACK_SUPPRESSION_OPTION_WINDOW: - tcp_ack->rx_window_scale = options[2]; - len = options[1]; - break; - default: - len = options[1]; - break; - } - /* if length field in TCP options is 0, or greater than - * total options length, then options are incorrect - */ - if ((len == 0) || (len >= optlen)) - break; - - if (optlen >= len) - optlen -= len; - else - optlen = 0; - options += len; - } - } - if (len > ((hlen * 4) + (tcp_hdr->doff * 4))) { - if (from_ba) - SCSC_HIP4_SAMPLER_TCP_DATA(sdev->minor_prof, tcp_ack->stream_id, tcp_hdr->seq); - else - SCSC_HIP4_SAMPLER_TCP_DATA_IN(sdev->minor_prof, tcp_ack->stream_id, tcp_hdr->seq); - } else { - if (tcp_ack->rx_window_scale) - rwnd = be16_to_cpu(tcp_hdr->window) * (2 << tcp_ack->rx_window_scale); - else - rwnd = be16_to_cpu(tcp_hdr->window); - if (from_ba) { - SCSC_HIP4_SAMPLER_TCP_ACK(sdev->minor_prof, tcp_ack->stream_id, be32_to_cpu(tcp_hdr->ack_seq)); - SCSC_HIP4_SAMPLER_TCP_RWND(sdev->minor_prof, tcp_ack->stream_id, rwnd); - } else { - SCSC_HIP4_SAMPLER_TCP_ACK_IN(sdev->minor_prof, tcp_ack->stream_id, be32_to_cpu(tcp_hdr->ack_seq)); - } - } - slsi_spinlock_unlock(&tcp_ack->lock); - break; - } - slsi_spinlock_unlock(&tcp_ack->lock); - } -} - -#ifdef CONFIG_SCSC_LOG_COLLECTION -int hip4_collect_init(struct scsc_log_collector_client *collect_client) -{ - /* Stop Sampling */ - atomic_set(&in_read, 1); - return 0; -} - -int hip4_collect(struct scsc_log_collector_client *collect_client, size_t size) -{ - int i = SCSC_HIP4_DEBUG_INTERFACES; - int ret = 0; - unsigned long flags; - u32 num_samples; - struct hip4_sampler_dev *hip4_dev; - void *buf; - - SLSI_INFO_NODEV("Triggered log collection in hip4_sampler\n"); - - if (!hip4_sampler_enable) - return 0; - - while (i--) - if (hip4_sampler.devs[i].mx == collect_client->prv && hip4_sampler.devs[i].type == OFFLINE) { - hip4_dev = &hip4_sampler.devs[i]; - num_samples = kfifo_len(&hip4_dev->fifo); - if (!num_samples) - continue; - buf = vmalloc(num_samples * sizeof(struct hip4_record)); - if (!buf) - continue; - spin_lock_irqsave(&g_spinlock, flags); - ret = kfifo_out(&hip4_dev->fifo, buf, num_samples); - spin_unlock_irqrestore(&g_spinlock, flags); - if (!ret) - goto error; - SLSI_DBG1_NODEV(SLSI_HIP, "num_samples %d ret %d size of hip4_record %zu\n", num_samples, ret, sizeof(struct hip4_record)); - ret = scsc_log_collector_write(buf, ret * sizeof(struct hip4_record), 1); - if (ret) - goto error; - vfree(buf); - } - return 0; -error: - vfree(buf); - return ret; -} - -int hip4_collect_end(struct scsc_log_collector_client *collect_client) -{ - /* Restart sampling */ - atomic_set(&in_read, 0); - return 0; -} - -/* Collect client registration */ -struct scsc_log_collector_client hip4_collect_client = { - .name = "HIP4 Sampler", - .type = SCSC_LOG_CHUNK_HIP4_SAMPLER, - .collect_init = hip4_collect_init, - .collect = hip4_collect, - .collect_end = hip4_collect_end, - .prv = NULL, -}; -#endif - -static int hip4_sampler_open(struct inode *inode, struct file *filp) -{ - struct hip4_sampler_dev *hip4_dev; - int ret = 0; - - hip4_dev = container_of(inode->i_cdev, struct hip4_sampler_dev, cdev); - - if (hip4_dev->type == OFFLINE) { - /* Offline buffer skip open */ - filp->private_data = hip4_dev; - return 0; - } - if (mutex_lock_interruptible(&hip4_dev->mutex)) - return -ERESTARTSYS; - - if (filp->private_data) { - SLSI_INFO_NODEV("Service already started\n"); - ret = 0; - goto end; - } - - if (hip4_sampler_kfifo_len > 256 * 1024) { - SLSI_DBG1_NODEV(SLSI_HIP, "hip4_sampler_kfifo_len %d > 2262144. Set to MAX", hip4_sampler_kfifo_len); - hip4_sampler_kfifo_len = 256 * 1024; - } - - ret = kfifo_alloc(&hip4_dev->fifo, hip4_sampler_kfifo_len, GFP_KERNEL); - if (ret) { - SLSI_ERR_NODEV("kfifo_alloc failed"); - ret = -ENOMEM; - goto end; - } - - filp->private_data = hip4_dev; - - /* Clear any remaining error */ - hip4_dev->error = NO_ERROR; - - hip4_dev->record_num = 0; - hip4_dev->kfifo_max = 0; - hip4_dev->filp = filp; - - SLSI_INFO_NODEV("%s: Sampling....\n", DRV_NAME); -end: - mutex_unlock(&hip4_dev->mutex); - return ret; -} - -static ssize_t hip4_sampler_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) -{ - unsigned int copied; - int ret = 0; - struct hip4_sampler_dev *hip4_dev; - - hip4_dev = filp->private_data; - - if (hip4_dev->type == OFFLINE) { - /* Offline buffer skip open */ - if (mutex_lock_interruptible(&hip4_dev->mutex)) - return -EINTR; - atomic_set(&in_read, 1); - ret = kfifo_to_user(&hip4_dev->fifo, buf, len, &copied); - mutex_unlock(&hip4_dev->mutex); - return ret ? ret : copied; - } - - if (mutex_lock_interruptible(&hip4_dev->mutex)) - return -EINTR; - - /* Check whether the device is in error */ - if (hip4_dev->error != NO_ERROR) { - SLSI_ERR_NODEV("Device in error\n"); - ret = -EIO; - goto end; - } - - while (len) { - if (kfifo_len(&hip4_dev->fifo)) { - ret = kfifo_to_user(&hip4_dev->fifo, buf, len, &copied); - if (!ret) - ret = copied; - break; - } - - if (filp->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - ret = wait_event_interruptible(hip4_dev->read_wait, - !kfifo_is_empty(&hip4_dev->fifo)); - if (ret < 0) - break; - } -end: - mutex_unlock(&hip4_dev->mutex); - return ret; -} - -static unsigned hip4_sampler_poll(struct file *filp, poll_table *wait) -{ - struct hip4_sampler_dev *hip4_dev; - int ret; - - hip4_dev = filp->private_data; - - if (hip4_dev->type == OFFLINE) - /* Offline buffer skip poll */ - return 0; - - if (mutex_lock_interruptible(&hip4_dev->mutex)) - return -EINTR; - - if (hip4_dev->error != NO_ERROR) { - ret = POLLERR; - goto end; - } - - poll_wait(filp, &hip4_dev->read_wait, wait); - - if (!kfifo_is_empty(&hip4_dev->fifo)) { - ret = POLLIN | POLLRDNORM; /* readeable */ - goto end; - } - - ret = POLLOUT | POLLWRNORM; /* writable */ - -end: - mutex_unlock(&hip4_dev->mutex); - return ret; -} - -static int hip4_sampler_release(struct inode *inode, struct file *filp) -{ - struct hip4_sampler_dev *hip4_dev; - - hip4_dev = container_of(inode->i_cdev, struct hip4_sampler_dev, cdev); - - if (hip4_dev->type == OFFLINE) { - atomic_set(&in_read, 0); - /* Offline buffer skip release */ - return 0; - } - - if (mutex_lock_interruptible(&hip4_dev->mutex)) - return -EINTR; - - if (!hip4_dev->filp) { - SLSI_ERR_NODEV("Device already closed\n"); - mutex_unlock(&hip4_dev->mutex); - return -EIO; - } - - if (hip4_dev != filp->private_data) { - SLSI_ERR_NODEV("Data mismatch\n"); - mutex_unlock(&hip4_dev->mutex); - return -EIO; - } - - filp->private_data = NULL; - hip4_dev->filp = NULL; - kfifo_free(&hip4_dev->fifo); - - mutex_unlock(&hip4_dev->mutex); - SLSI_INFO_NODEV("%s: Sampling... end. Kfifo_max = %d\n", DRV_NAME, hip4_dev->kfifo_max); - return 0; -} - -static const struct file_operations hip4_sampler_fops = { - .owner = THIS_MODULE, - .open = hip4_sampler_open, - .read = hip4_sampler_read, - .release = hip4_sampler_release, - .poll = hip4_sampler_poll, -}; - -/* Return minor (if exists) associated with this maxwell instance */ -int hip4_sampler_register_hip(struct scsc_mx *mx) -{ - int i = SCSC_HIP4_DEBUG_INTERFACES; - - while (i--) - if (hip4_sampler.devs[i].mx == mx && - hip4_sampler.devs[i].type == STREAMING) - return i; - return -ENODEV; -} - -void hip4_sampler_create(struct slsi_dev *sdev, struct scsc_mx *mx) -{ - dev_t devn; - int ret; - char dev_name[20]; - int minor; - int i; - - SLSI_INFO_NODEV("hip4_sampler version: %d.%d\n", VER_MAJOR, VER_MINOR); - - memset(&hip4_sampler, 0, sizeof(hip4_sampler)); - /* Check whether exists */ - if (!hip4_sampler.init) { - ret = alloc_chrdev_region(&hip4_sampler.device, 0, SCSC_HIP4_DEBUG_INTERFACES, "hip4_sampler_char"); - if (ret) - goto error; - - hip4_sampler.class_hip4_sampler = class_create(THIS_MODULE, DEVICE_NAME); - if (IS_ERR(hip4_sampler.class_hip4_sampler)) { - SLSI_ERR_NODEV("hip4_sampler class creation failed\n"); - ret = PTR_ERR(hip4_sampler.class_hip4_sampler); - goto error_class; - } - } - - /* Search for free minors */ - minor = find_first_zero_bit(bitmap_hip4_sampler_minor, SCSC_HIP4_DEBUG_INTERFACES); - if (minor == SCSC_HIP4_DEBUG_INTERFACES) { - SLSI_INFO_NODEV("minor %d > SCSC_TTY_MINORS\n", minor); - return; - } - - /* Create Stream channels */ - /* Each Stream channel will have an associated Offline channel */ - for (i = 0; i < SCSC_HIP4_STREAM_CH; i++) { - minor += i; - devn = MKDEV(MAJOR(hip4_sampler.device), MINOR(minor)); - - snprintf(dev_name, sizeof(dev_name), "%s_%d_%s", "hip4", i, "sam_str"); - - cdev_init(&hip4_sampler.devs[minor].cdev, &hip4_sampler_fops); - hip4_sampler.devs[minor].cdev.owner = THIS_MODULE; - hip4_sampler.devs[minor].cdev.ops = &hip4_sampler_fops; - - ret = cdev_add(&hip4_sampler.devs[minor].cdev, devn, 1); - if (ret) { - hip4_sampler.devs[minor].cdev.dev = 0; - return; - } - - hip4_sampler.devs[minor].dev = - device_create(hip4_sampler.class_hip4_sampler, NULL, hip4_sampler.devs[minor].cdev.dev, NULL, dev_name); - - if (!hip4_sampler.devs[minor].dev) { - SLSI_ERR_NODEV("dev is NULL\n"); - hip4_sampler.devs[minor].cdev.dev = 0; - cdev_del(&hip4_sampler.devs[minor].cdev); - return; - } - - hip4_sampler.devs[minor].mx = mx; - - mutex_init(&hip4_sampler.devs[minor].mutex); - hip4_sampler.devs[minor].kfifo_max = 0; - hip4_sampler.devs[minor].type = STREAMING; - hip4_sampler.devs[minor].minor = minor; - - init_waitqueue_head(&hip4_sampler.devs[minor].read_wait); - - slsi_traffic_mon_client_register( - sdev, - &hip4_sampler.devs[minor], - TRAFFIC_MON_CLIENT_MODE_PERIODIC, - 0, - 0, - hip4_sampler_tput_monitor); - - /* Update bit mask */ - set_bit(minor, bitmap_hip4_sampler_minor); - - minor++; - - /* Create associated offline channel */ - devn = MKDEV(MAJOR(hip4_sampler.device), MINOR(minor)); - - snprintf(dev_name, sizeof(dev_name), "%s_%d_%s", "hip4", i, "sam_off"); - - cdev_init(&hip4_sampler.devs[minor].cdev, &hip4_sampler_fops); - hip4_sampler.devs[minor].cdev.owner = THIS_MODULE; - hip4_sampler.devs[minor].cdev.ops = &hip4_sampler_fops; - - ret = cdev_add(&hip4_sampler.devs[minor].cdev, devn, 1); - if (ret) { - hip4_sampler.devs[minor].cdev.dev = 0; - return; - } - - hip4_sampler.devs[minor].dev = - device_create(hip4_sampler.class_hip4_sampler, NULL, hip4_sampler.devs[minor].cdev.dev, NULL, dev_name); - - if (!hip4_sampler.devs[minor].dev) { - hip4_sampler.devs[minor].cdev.dev = 0; - cdev_del(&hip4_sampler.devs[minor].cdev); - return; - } - - if (hip4_sampler_static_kfifo_len > 256 * 1024) { - SLSI_DBG1_NODEV(SLSI_HIP, "hip4_sampler_static_kfifo_len %d > 2262144. Set to MAX", hip4_sampler_static_kfifo_len); - hip4_sampler_static_kfifo_len = 256 * 1024; - } - ret = kfifo_alloc(&hip4_sampler.devs[minor].fifo, hip4_sampler_static_kfifo_len, GFP_KERNEL); - if (ret) { - SLSI_ERR_NODEV("kfifo_alloc failed"); - hip4_sampler.devs[minor].dev = NULL; - hip4_sampler.devs[minor].cdev.dev = 0; - cdev_del(&hip4_sampler.devs[minor].cdev); - return; - } - - hip4_sampler.devs[minor].mx = mx; - - mutex_init(&hip4_sampler.devs[minor].mutex); - hip4_sampler.devs[minor].kfifo_max = 0; - hip4_sampler.devs[minor].type = OFFLINE; - - /* Update bit mask */ - set_bit(minor, bitmap_hip4_sampler_minor); - } - -#ifdef CONFIG_SCSC_LOG_COLLECTION - hip4_collect_client.prv = mx; - scsc_log_collector_register_client(&hip4_collect_client); -#endif - spin_lock_init(&g_spinlock); - hip4_sampler.init = true; - - SLSI_INFO_NODEV("%s: Ready to start sampling....\n", DRV_NAME); - - return; - -error_class: - unregister_chrdev_region(hip4_sampler.device, SCSC_HIP4_DEBUG_INTERFACES); - hip4_sampler.init = false; -error: - return; -} - -void hip4_sampler_destroy(struct slsi_dev *sdev, struct scsc_mx *mx) -{ - int i = SCSC_HIP4_DEBUG_INTERFACES; - struct hip4_sampler_dev *hip4_dev; - - while (i--) - if (hip4_sampler.devs[i].cdev.dev && hip4_sampler.devs[i].mx) { - hip4_dev = &hip4_sampler.devs[i]; - /* This should be never be true - as knod should prevent unloading while - * the service (device node) is open - */ - if (hip4_sampler.devs[i].filp) { - hip4_sampler.devs[i].filp = NULL; - kfifo_free(&hip4_sampler.devs[i].fifo); - } - if (hip4_sampler.devs[i].type == OFFLINE) - kfifo_free(&hip4_sampler.devs[i].fifo); - - slsi_traffic_mon_client_unregister(sdev, hip4_dev); - device_destroy(hip4_sampler.class_hip4_sampler, hip4_sampler.devs[i].cdev.dev); - cdev_del(&hip4_sampler.devs[i].cdev); - memset(&hip4_sampler.devs[i].cdev, 0, sizeof(struct cdev)); - hip4_sampler.devs[i].mx = NULL; - clear_bit(i, bitmap_hip4_sampler_minor); - } -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_unregister_client(&hip4_collect_client); -#endif - class_destroy(hip4_sampler.class_hip4_sampler); - unregister_chrdev_region(hip4_sampler.device, SCSC_HIP4_DEBUG_INTERFACES); - hip4_sampler.init = false; -} diff --git a/drivers/net/wireless/scsc/hip4_sampler.h b/drivers/net/wireless/scsc/hip4_sampler.h deleted file mode 100644 index ddb798d0d3d0..000000000000 --- a/drivers/net/wireless/scsc/hip4_sampler.h +++ /dev/null @@ -1,412 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include - -#include "dev.h" - -/* TCP send buffer sizes */ -extern int sysctl_tcp_wmem[3]; - -#ifndef __HIP4_SAMPLER_H__ -#define __HIP4_SAMPLER_H__ - -#define HIP4_SAMPLER_SIGNAL_CTRLTX 0x20 -#define HIP4_SAMPLER_SIGNAL_CTRLRX 0x21 -#define HIP4_SAMPLER_THROUG 0x22 -#define HIP4_SAMPLER_THROUG_K 0x23 -#define HIP4_SAMPLER_THROUG_M 0x24 -#define HIP4_SAMPLER_STOP_Q 0x25 -#define HIP4_SAMPLER_START_Q 0x26 -#define HIP4_SAMPLER_QREF 0x27 -#define HIP4_SAMPLER_PEER 0x29 -#define HIP4_SAMPLER_BOT_RX 0x2a -#define HIP4_SAMPLER_BOT_TX 0x2b -#define HIP4_SAMPLER_BOT_ADD 0x2c -#define HIP4_SAMPLER_BOT_REMOVE 0x2d -#define HIP4_SAMPLER_BOT_STOP_Q 0x2e -#define HIP4_SAMPLER_BOT_START_Q 0x2f -#define HIP4_SAMPLER_BOT_QMOD_RX 0x30 -#define HIP4_SAMPLER_BOT_QMOD_TX 0x31 -#define HIP4_SAMPLER_BOT_QMOD_STOP 0x32 -#define HIP4_SAMPLER_BOT_QMOD_START 0x33 -#define HIP4_SAMPLER_PKT_TX 0x40 -#define HIP4_SAMPLER_PKT_TX_HIP4 0x41 -#define HIP4_SAMPLER_PKT_TX_FB 0x42 -#define HIP4_SAMPLER_SUSPEND 0x50 -#define HIP4_SAMPLER_RESUME 0x51 - -#define HIP4_SAMPLER_TCP_SYN 0x60 -#define HIP4_SAMPLER_TCP_FIN 0x61 -#define HIP4_SAMPLER_TCP_DATA 0x62 -#define HIP4_SAMPLER_TCP_ACK 0x63 -#define HIP4_SAMPLER_TCP_RWND 0x64 -#define HIP4_SAMPLER_TCP_CWND 0x65 -#define HIP4_SAMPLER_TCP_SEND_BUF 0x66 -#define HIP4_SAMPLER_TCP_DATA_IN 0x67 -#define HIP4_SAMPLER_TCP_ACK_IN 0x68 - -#define HIP4_SAMPLER_MBULK 0xaa -#define HIP4_SAMPLER_QFULL 0xbb -#define HIP4_SAMPLER_MFULL 0xcc -#define HIP4_SAMPLER_INT 0xdd -#define HIP4_SAMPLER_INT_OUT 0xee -#define HIP4_SAMPLER_INT_BH 0xde -#define HIP4_SAMPLER_INT_OUT_BH 0xef -#define HIP4_SAMPLER_RESET 0xff - -#define SCSC_HIP4_INTERFACES 1 - -#define SCSC_HIP4_STREAM_CH 1 -#define SCSC_HIP4_OFFLINE_CH SCSC_HIP4_STREAM_CH - -#if (SCSC_HIP4_OFFLINE_CH != SCSC_HIP4_STREAM_CH) -#error "SCSC_HIP4_STREAM_CH has to be equal to SCSC_HIP4_OFFLINE_CH" -#endif - -#define SCSC_HIP4_DEBUG_INTERFACES ((SCSC_HIP4_INTERFACES) * (SCSC_HIP4_STREAM_CH + SCSC_HIP4_OFFLINE_CH)) - -struct scsc_mx; - -void hip4_sampler_create(struct slsi_dev *sdev, struct scsc_mx *mx); -void hip4_sampler_destroy(struct slsi_dev *sdev, struct scsc_mx *mx); - -/* Register hip4 instance with the logger */ -/* return char device minor associated with the maxwell instance*/ -int hip4_sampler_register_hip(struct scsc_mx *mx); - -void hip4_sampler_update_record(u32 minor, u8 param1, u8 param2, u8 param3, u8 param4, u32 param5); -void hip4_sampler_tcp_decode(struct slsi_dev *sdev, struct net_device *dev, u8 *frame, bool from_ba); - -extern bool hip4_sampler_sample_q; -extern bool hip4_sampler_sample_qref; -extern bool hip4_sampler_sample_int; -extern bool hip4_sampler_sample_fapi; -extern bool hip4_sampler_sample_through; -extern bool hip4_sampler_sample_tcp; -extern bool hip4_sampler_sample_start_stop_q; -extern bool hip4_sampler_sample_mbulk; -extern bool hip4_sampler_sample_qfull; -extern bool hip4_sampler_sample_mfull; -extern bool hip4_sampler_vif; -extern bool hip4_sampler_bot; -extern bool hip4_sampler_pkt_tx; -extern bool hip4_sampler_suspend_resume; - -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING -#define SCSC_HIP4_SAMPLER_Q(minor, q, idx_rw, value, rw) \ - do { \ - if (hip4_sampler_sample_q) { \ - hip4_sampler_update_record(minor, q, idx_rw, value, rw, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_QREF(minor, ref, q) \ - do { \ - if (hip4_sampler_sample_qref) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_QREF, (ref & 0xff0000) >> 16, (ref & 0xff00) >> 8, (ref & 0xf0) | q, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_SIGNAL_CTRLTX(minor, bytes16_h, bytes16_l) \ - do { \ - if (hip4_sampler_sample_fapi) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_SIGNAL_CTRLTX, 0, bytes16_h, bytes16_l, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_SIGNAL_CTRLRX(minor, bytes16_h, bytes16_l) \ - do { \ - if (hip4_sampler_sample_fapi) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_SIGNAL_CTRLRX, 0, bytes16_h, bytes16_l, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_TCP_DECODE(sdev, dev, frame, from_ba) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_tcp_decode(sdev, dev, frame, from_ba); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_THROUG(minor, rx_tx, bytes16_h, bytes16_l) \ - do { \ - if (hip4_sampler_sample_through) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_THROUG, rx_tx, bytes16_h, bytes16_l, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_THROUG_K(minor, rx_tx, bytes16_h, bytes16_l) \ - do { \ - if (hip4_sampler_sample_through) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_THROUG_K, rx_tx, bytes16_h, bytes16_l, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_THROUG_M(minor, rx_tx, bytes16_h, bytes16_l) \ - do { \ - if (hip4_sampler_sample_through) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_THROUG_M, rx_tx, bytes16_h, bytes16_l, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_STOP_Q(minor, vif_id) \ - do { \ - if (hip4_sampler_sample_start_stop_q) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_STOP_Q, 0, 0, vif_id, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_START_Q(minor, vif_id) \ - do { \ - if (hip4_sampler_sample_start_stop_q) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_START_Q, 0, 0, vif_id, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_MBULK(minor, bytes16_h, bytes16_l, clas) \ - do { \ - if (hip4_sampler_sample_mbulk) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_MBULK, clas, bytes16_h, bytes16_l, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_QFULL(minor, q) \ - do { \ - if (hip4_sampler_sample_qfull) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_QFULL, 0, 0, q, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_MFULL(minor) \ - do { \ - if (hip4_sampler_sample_mfull) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_MFULL, 0, 0, 0, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_INT(minor, id) \ - do { \ - if (hip4_sampler_sample_int) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_INT, 0, 0, id, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_INT_OUT(minor, id) \ - do { \ - if (hip4_sampler_sample_int) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_INT_OUT, 0, 0, id, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_INT_BH(minor, id) \ - do { \ - if (hip4_sampler_sample_int) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_INT_BH, 0, 0, id, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_INT_OUT_BH(minor, id) \ - do { \ - if (hip4_sampler_sample_int) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_INT_OUT_BH, 0, 0, id, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_RESET(minor) \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_RESET, 0, 0, 0, 0) - -#define SCSC_HIP4_SAMPLER_VIF_PEER(minor, tx, vif, peer_index) \ - do { \ - if (hip4_sampler_vif) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_PEER, tx, vif, peer_index, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_BOT_RX(minor, scod, smod, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_RX, scod, smod, vif_peer, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_BOT_TX(minor, scod, smod, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_TX, scod, smod, vif_peer, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_BOT_ADD(minor, addr_1, addr_2, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_ADD, addr_1, addr_2, vif_peer, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_BOT_REMOVE(minor, addr_1, addr_2, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_REMOVE, addr_1, addr_2, vif_peer, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_BOT_START_Q(minor, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_START_Q, 0, 0, vif_peer, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_BOT_STOP_Q(minor, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_STOP_Q, 0, 0, vif_peer, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_BOT_QMOD_RX(minor, qcod, qmod, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_QMOD_RX, qcod, qmod, vif_peer, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_BOT_QMOD_TX(minor, qcod, qmod, vif_peer) \ - do { \ - if (hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_QMOD_TX, qcod, qmod, vif_peer, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_BOT_QMOD_START(minor, vif_peer) \ - do { \ - if (hip4_sampler_sample_start_stop_q || hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_QMOD_START, 0, 0, vif_peer, 0); \ - } \ - } while (0) - -#define SCSC_HIP4_SAMPLER_BOT_QMOD_STOP(minor, vif_peer) \ - do { \ - if (hip4_sampler_sample_start_stop_q || hip4_sampler_bot) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_BOT_QMOD_STOP, 0, 0, vif_peer, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_PKT_TX(minor, host_tag) \ - do { \ - if (hip4_sampler_pkt_tx) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_PKT_TX, 0, (host_tag >> 8) & 0xff, host_tag & 0xff, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_PKT_TX_HIP4(minor, host_tag) \ - do { \ - if (hip4_sampler_pkt_tx) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_PKT_TX_HIP4, 0, (host_tag >> 8) & 0xff, host_tag & 0xff, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_PKT_TX_FB(minor, host_tag) \ - do { \ - if (hip4_sampler_pkt_tx) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_PKT_TX_FB, 0, (host_tag >> 8) & 0xff, host_tag & 0xff, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_SUSPEND(minor) \ - do { \ - if (hip4_sampler_suspend_resume) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_SUSPEND, 0, 0, 0, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_RESUME(minor) \ - do { \ - if (hip4_sampler_suspend_resume) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_RESUME, 0, 0, 0, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_SYN(minor, id, mss) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_SYN, id, 0, 0, mss); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_FIN(minor, id) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_FIN, id, 0, 0, 0); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_DATA(minor, id, seq_num) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_DATA, id, 0, 0, seq_num); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_ACK(minor, id, ack_num) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_ACK, id, 0, 0, ack_num); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_DATA_IN(minor, id, seq_num) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_DATA_IN, id, 0, 0, seq_num); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_ACK_IN(minor, id, ack_num) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_ACK_IN, id, 0, 0, ack_num); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_RWND(minor, id, rwnd) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_RWND, id, 0, 0, rwnd); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_CWND(minor, id, cwnd) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_CWND, id, 0, 0, cwnd); \ - } \ - } while (0) -#define SCSC_HIP4_SAMPLER_TCP_SEND_BUF(minor, id, send_buff_size) \ - do { \ - if (hip4_sampler_sample_tcp) { \ - hip4_sampler_update_record(minor, HIP4_SAMPLER_TCP_SEND_BUF, id, 0, 0, send_buff_size); \ - } \ - } while (0) -#else -#define SCSC_HIP4_SAMPLER_Q(minor, q, idx_rw, value, rw) -#define SCSC_HIP4_SAMPLER_QREF(minor, ref, q) -#define SCSC_HIP4_SAMPLER_SIGNAL_CTRLTX(minor, bytes16_h, bytes16_l) -#define SCSC_HIP4_SAMPLER_SIGNAL_CTRLRX(minor, bytes16_h, bytes16_l) -#define SCSC_HIP4_SAMPLER_TPUT(minor, rx_tx, payload) -#define SCSC_HIP4_SAMPLER_THROUG(minor, bytes16_h, bytes16_l) -#define SCSC_HIP4_SAMPLER_THROUG_K(minor, bytes16_h, bytes16_l) -#define SCSC_HIP4_SAMPLER_THROUG_M(minor, bytes16_h, bytes16_l) -#define SCSC_HIP4_SAMPLER_MBULK(minor, bytes16_h, bytes16_l, clas) -#define SCSC_HIP4_SAMPLER_QFULL(minor, q) -#define SCSC_HIP4_SAMPLER_MFULL(minor) -#define SCSC_HIP4_SAMPLER_INT(minor, id) -#define SCSC_HIP4_SAMPLER_INT_BH(minor, id) -#define SCSC_HIP4_SAMPLER_INT_OUT(minor, id) -#define SCSC_HIP4_SAMPLER_INT_OUT_BH(minor, id) -#define SCSC_HIP4_SAMPLER_RESET(minor) -#define SCSC_HIP4_SAMPLER_VIF_PEER(minor, tx, vif, peer_index) -#define SCSC_HIP4_SAMPLER_BOT_RX(minor, scod, smod, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_TX(minor, scod, smod, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT(minor, init, addr_1, addr_2, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_ADD(minor, addr_1, addr_2, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_REMOVE(minor, addr_1, addr_2, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_START_Q(minor, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_STOP_Q(minor, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_QMOD_RX(minor, qcod, qmod, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_QMOD_TX(minor, qcod, qmod, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_QMOD_START(minor, vif_peer) -#define SCSC_HIP4_SAMPLER_BOT_QMOD_STOP(minor, vif_peer) -#define SCSC_HIP4_SAMPLER_PKT_TX(minor, host_tag) -#define SCSC_HIP4_SAMPLER_PKT_TX_HIP4(minor, host_tag) -#define SCSC_HIP4_SAMPLER_PKT_TX_FB(minor, host_tag) -#define SCSC_HIP4_SAMPLER_SUSPEND(minor) -#define SCSC_HIP4_SAMPLER_RESUME(minor) -#define SCSC_HIP4_SAMPLER_TCP_SYN(minor, id, mss) -#define SCSC_HIP4_SAMPLER_TCP_FIN(minor, id) -#define SCSC_HIP4_SAMPLER_TCP_DATA(minor, id, seq_num) -#define SCSC_HIP4_SAMPLER_TCP_ACK(minor, id, ack_num) -#define SCSC_HIP4_SAMPLER_TCP_DATA_IN(minor, id, seq_num) -#define SCSC_HIP4_SAMPLER_TCP_ACK_IN(minor, id, ack_num) -#define SCSC_HIP4_SAMPLER_TCP_RWND(minor, id, rwnd) -#define SCSC_HIP4_SAMPLER_TCP_CWND(minor, id, cwnd) -#define SCSC_HIP4_SAMPLER_TCP_SEND_BUF(minor, id, send_buff_size) -#define SCSC_HIP4_SAMPLER_TCP_DECODE(sdev, dev, frame, from_ba) -#endif /* CONFIG_SCSC_WLAN_HIP4_PROFILING */ - -#endif /* __HIP4_SAMPLER_H__ */ diff --git a/drivers/net/wireless/scsc/hip4_smapper.c b/drivers/net/wireless/scsc/hip4_smapper.c deleted file mode 100644 index 2d3678670378..000000000000 --- a/drivers/net/wireless/scsc/hip4_smapper.c +++ /dev/null @@ -1,432 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include -#include -#include -#include - -#include "debug.h" -#include "dev.h" -#include "hip4.h" -#include "hip4_smapper.h" - -#define SMAPPER_GRANULARITY (4 * 1024) - -static void hip4_smapper_refill_isr(int irq, void *data); - -static int hip4_smapper_alloc_bank(struct slsi_dev *sdev, struct hip4_priv *priv, enum smapper_banks bank_name, u32 entry_size, bool is_large) -{ - u16 i; - struct hip4_smapper_bank *bank = &(priv)->smapper_banks[bank_name]; - struct hip4_smapper_control *control = &(priv)->smapper_control; - int err; - - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Init bank %d entry_size %d is_large %d\n", bank_name, entry_size, is_large); - bank->entry_size = entry_size; - - /* function returns negative number if an error occurs, otherwise returns the bank number */ - err = scsc_service_mifsmapper_alloc_bank(sdev->service, is_large, bank->entry_size, &bank->entries); - if (err < 0) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Error allocating bank %d\n", err); - return -ENOMEM; - } - - bank->bank = (u32)err; - if (bank->bank >= HIP4_SMAPPER_TOTAL_BANKS) { - scsc_service_mifsmapper_free_bank(sdev->service, bank->bank); - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Incorrect bank_num %d\n", bank->bank); - return -ENOMEM; - } - - bank->skbuff = kmalloc_array(bank->entries, sizeof(struct sk_buff *), - GFP_KERNEL); - bank->skbuff_dma = kmalloc_array(bank->entries, sizeof(dma_addr_t), - GFP_KERNEL); - if (!bank->skbuff || !bank->skbuff_dma) { - kfree(bank->skbuff_dma); - kfree(bank->skbuff); - return -ENOMEM; - } - - for (i = 0; i < bank->entries; i++) - bank->skbuff[i] = NULL; - - bank->align = scsc_service_get_alignment(sdev->service); - bank->in_use = true; - - /* update the mapping with BANK# in WLAN with PHY BANK#*/ - control->lookuptable[bank->bank] = bank_name; - - return 0; -} - -static int hip4_smapper_allocate_skb_buffer_entry(struct slsi_dev *sdev, struct hip4_smapper_bank *bank, int idx) -{ - struct sk_buff *skb; - int err; - - skb = slsi_alloc_skb(bank->entry_size, GFP_ATOMIC); - if (!skb) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Not enough memory\n"); - return -ENOMEM; - } - SLSI_DBG4_NODEV(SLSI_SMAPPER, "SKB allocated: 0x%p at bank %d entry %d\n", skb, bank->bank, idx); - bank->skbuff_dma[idx] = dma_map_single(sdev->dev, skb->data, - bank->entry_size, DMA_FROM_DEVICE); - err = dma_mapping_error(sdev->dev, bank->skbuff_dma[idx]); - if (err) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Error mapping SKB: 0x%p at bank %d entry %d\n", skb, bank->bank, idx); - slsi_kfree_skb(skb); - return err; - } - - /* Check alignment */ - if (!IS_ALIGNED(bank->skbuff_dma[idx], bank->align)) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Phys address: 0x%x not %d aligned. Unmap memory and return error\n", - bank->skbuff_dma[idx], bank->align); - dma_unmap_single(sdev->dev, bank->skbuff_dma[idx], bank->entry_size, DMA_FROM_DEVICE); - slsi_kfree_skb(skb); - bank->skbuff_dma[idx] = 0; - return -ENOMEM; - } - bank->skbuff[idx] = skb; - return 0; -} - -/* Pre-Allocate the skbs for the RX entries */ -static int hip4_smapper_allocate_skb_buffers(struct slsi_dev *sdev, struct hip4_smapper_bank *bank) -{ - unsigned int i; - unsigned int n; - int res; - - if (!bank) - return -EINVAL; - - n = bank->entries; - for (i = 0; i < n; i++) { - if (!bank->skbuff[i]) { - res = hip4_smapper_allocate_skb_buffer_entry(sdev, bank, i); - if (res != 0) - return res; - } - } - - return 0; -} - -static int hip4_smapper_free_skb_buffers(struct slsi_dev *sdev, struct hip4_smapper_bank *bank) -{ - unsigned int i; - unsigned int n; - - if (!bank) - return -EINVAL; - - n = bank->entries; - for (i = 0; i < n; i++) { - if (bank->skbuff[i]) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "SKB free: 0x%p at bank %d entry %d\n", bank->skbuff[i], bank->bank, i); - dma_unmap_single(sdev->dev, bank->skbuff_dma[i], bank->entry_size, DMA_FROM_DEVICE); - bank->skbuff_dma[i] = 0; - slsi_kfree_skb(bank->skbuff[i]); - bank->skbuff[i] = NULL; - } - } - - return 0; -} - -static int hip4_smapper_program(struct slsi_dev *sdev, struct hip4_smapper_bank *bank) -{ - unsigned int n; - - if (!bank) - return -EINVAL; - - n = bank->entries; - - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Programming Bank %d\n", bank->bank); - - return scsc_service_mifsmapper_write_sram(sdev->service, bank->bank, n, 0, bank->skbuff_dma); -} - -/* refill ISR. FW signals the Host whenever it wants to refill the smapper buffers */ -/* Only the Host Owned Buffers should be refilled */ -static void hip4_smapper_refill_isr(int irq, void *data) -{ - struct slsi_hip4 *hip = (struct slsi_hip4 *)data; - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - struct hip4_smapper_control *control; - struct hip4_smapper_bank *bank; - enum smapper_banks i; - unsigned long flags; - /* Temporary removed - * static DEFINE_RATELIMIT_STATE(ratelimit, 1 * HZ, 1); - */ - - control = &(hip->hip_priv->smapper_control); -#ifdef CONFIG_SCSC_QOS - /* Ignore request if TPUT is low or platform is in suspend */ - if (hip->hip_priv->pm_qos_state == SCSC_QOS_DISABLED || - atomic_read(&hip->hip_priv->in_suspend) || - *control->mbox_ptr == 0x0) { -#else - /* Ignore if platform is in suspend */ - if (atomic_read(&hip->hip_priv->in_suspend) || - *control->mbox_ptr == 0x0) { -#endif - /* - * Temporary removed - * if (__ratelimit(&ratelimit)) - * SLSI_DBG1_NODEV(SLSI_SMAPPER, "Ignore SMAPPER request. Invalid state.\n"); - */ - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(sdev->service, control->th_req); - return; - } - - spin_lock_irqsave(&control->smapper_lock, flags); - /* Check if FW has requested a BANK configuration */ - if (HIP4_SMAPPER_BANKS_CHECK_CONFIGURE(*control->mbox_ptr)) { - /* Temporary removed - * SLSI_DBG4_NODEV(SLSI_SMAPPER, "Trigger SMAPPER configuration\n"); - */ - scsc_service_mifsmapper_configure(sdev->service, SMAPPER_GRANULARITY); - HIP4_SMAPPER_BANKS_CONFIGURE_DONE(*control->mbox_ptr); - } - /* Read the first RX bank and check whether needs to be reprogrammed */ - for (i = RX_0; i < END_RX_BANKS; i++) { - bank = &hip->hip_priv->smapper_banks[i]; - - if (!bank->in_use) - continue; - - if (HIP4_SMAPPER_GET_BANK_OWNER(bank->bank, *control->mbox_ptr) == HIP_SMAPPER_OWNER_HOST) { - /* Temporary removed - * SLSI_DBG4_NODEV(SLSI_SMAPPER, "SKB allocation at bank %d\n", i); - */ - if (hip4_smapper_allocate_skb_buffers(sdev, bank)) { - /* Temporary removed - * SLSI_DBG4_NODEV(SLSI_SMAPPER, "Error Allocating skb buffers at bank %d. Setting owner to FW\n", i); - */ - HIP4_SMAPPER_SET_BANK_OWNER(bank->bank, *control->mbox_ptr, HIP_SMAPPER_OWNER_FW); - continue; - } - if (hip4_smapper_program(sdev, bank)) { - /* Temporary removed - * SLSI_DBG4_NODEV(SLSI_SMAPPER, "Error Programming bank %d. Setting owner to FW\n", i); - */ - HIP4_SMAPPER_SET_BANK_OWNER(bank->bank, *control->mbox_ptr, HIP_SMAPPER_OWNER_FW); - continue; - } - HIP4_SMAPPER_SET_BANK_STATE(bank->bank, *control->mbox_ptr, HIP_SMAPPER_STATUS_MAPPED); - HIP4_SMAPPER_SET_BANK_OWNER(bank->bank, *control->mbox_ptr, HIP_SMAPPER_OWNER_FW); - } - } - /* Inform FW that entries have been programmed */ - scsc_service_mifintrbit_bit_set(sdev->service, control->fh_ind, SCSC_MIFINTR_TARGET_R4); - - /* Clear interrupt */ - scsc_service_mifintrbit_bit_clear(sdev->service, control->th_req); - - spin_unlock_irqrestore(&control->smapper_lock, flags); -} - -int hip4_smapper_consume_entry(struct slsi_dev *sdev, struct slsi_hip4 *hip, struct sk_buff *skb_fapi) -{ - struct sk_buff *skb; - struct hip4_smapper_bank *bank; - u8 bank_num; - u8 entry; - u16 len; - u16 headroom; - struct hip4_smapper_descriptor *desc; - struct hip4_smapper_control *control; - struct slsi_skb_cb *cb = slsi_skb_cb_get(skb_fapi); - - control = &(hip->hip_priv->smapper_control); - - desc = (struct hip4_smapper_descriptor *)skb_fapi->data; - - bank_num = desc->bank_num; - entry = desc->entry_num; - len = desc->entry_size; - headroom = desc->headroom; - - - if (bank_num >= HIP4_SMAPPER_TOTAL_BANKS) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Incorrect bank_num %d\n", bank_num); - goto error; - } - - /* Transform PHY BANK# with BANK# in Wlan service*/ - bank_num = control->lookuptable[bank_num]; - - bank = &hip->hip_priv->smapper_banks[bank_num]; - - if (entry > bank->entries) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Incorrect entry number %d\n", entry); - goto error; - } - - if (len > bank->entry_size) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Incorrect entry len %d\n", len); - goto error; - } - - skb = bank->skbuff[entry]; - if (!skb) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "SKB IS NULL at bank %d entry %d\n", bank_num, entry); - goto error; - } - - bank->skbuff[entry] = NULL; - dma_unmap_single(sdev->dev, bank->skbuff_dma[entry], bank->entry_size, DMA_FROM_DEVICE); - bank->skbuff_dma[entry] = 0; - - hip4_smapper_allocate_skb_buffer_entry(sdev, bank, entry); - - skb_reserve(skb, headroom); - skb_put(skb, len); - cb->skb_addr = skb; - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Consumed Bank %d Entry %d Len %d SKB smapper: 0x%p, SKB fapi %p\n", bank_num, entry, len, skb, skb_fapi); - - return 0; -error: - /* RX is broken.....*/ - return -EIO; -} - -void *hip4_smapper_get_skb_data(struct slsi_dev *sdev, struct slsi_hip4 *hip, struct sk_buff *skb_fapi) -{ - struct sk_buff *skb; - struct slsi_skb_cb *cb = slsi_skb_cb_get(skb_fapi); - struct hip4_smapper_control *control; - - control = &(hip->hip_priv->smapper_control); - - skb = (struct sk_buff *)cb->skb_addr; - - if (!skb) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "NULL SKB smapper\n"); - return NULL; - } - - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Get SKB smapper: 0x%p, SKB fapi 0x%p\n", skb, skb_fapi); - return skb->data; -} - -struct sk_buff *hip4_smapper_get_skb(struct slsi_dev *sdev, struct slsi_hip4 *hip, struct sk_buff *skb_fapi) -{ - struct sk_buff *skb; - struct slsi_skb_cb *cb = slsi_skb_cb_get(skb_fapi); - struct hip4_smapper_control *control; - - control = &(hip->hip_priv->smapper_control); - - skb = (struct sk_buff *)cb->skb_addr; - - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Get SKB smapper: 0x%p, SKB fapi 0x%p\n", skb, skb_fapi); - cb->free_ma_unitdat = true; - slsi_kfree_skb(skb_fapi); - - return skb; -} - -int hip4_smapper_init(struct slsi_dev *sdev, struct slsi_hip4 *hip) -{ - u8 i; - struct hip4_smapper_control *control; - - SLSI_DBG4_NODEV(SLSI_SMAPPER, "SMAPPER init\n"); - - control = &(hip->hip_priv->smapper_control); - - spin_lock_init(&control->smapper_lock); - - if (dma_set_mask_and_coherent(sdev->dev, DMA_BIT_MASK(64)) != 0) - return -EIO; - - if (!scsc_mx_service_alloc_mboxes(sdev->service, 1, &control->mbox_scb)) { - SLSI_DBG4_NODEV(SLSI_SMAPPER, "Unable to allocate mbox\n"); - return -ENODEV; - } - - /* Claim the RX buffers */ - hip4_smapper_alloc_bank(sdev, hip->hip_priv, RX_0, SMAPPER_GRANULARITY, HIP4_SMAPPER_BANK_LARGE); - hip4_smapper_alloc_bank(sdev, hip->hip_priv, RX_1, SMAPPER_GRANULARITY, HIP4_SMAPPER_BANK_LARGE); - hip4_smapper_alloc_bank(sdev, hip->hip_priv, RX_2, SMAPPER_GRANULARITY, HIP4_SMAPPER_BANK_LARGE); - hip4_smapper_alloc_bank(sdev, hip->hip_priv, RX_3, SMAPPER_GRANULARITY, HIP4_SMAPPER_BANK_LARGE); - /*Pre-allocate buffers */ - hip4_smapper_allocate_skb_buffers(sdev, &hip->hip_priv->smapper_banks[RX_0]); - hip4_smapper_allocate_skb_buffers(sdev, &hip->hip_priv->smapper_banks[RX_1]); - hip4_smapper_allocate_skb_buffers(sdev, &hip->hip_priv->smapper_banks[RX_2]); - hip4_smapper_allocate_skb_buffers(sdev, &hip->hip_priv->smapper_banks[RX_3]); - - /* Allocate Maxwell resources */ - control->th_req = - scsc_service_mifintrbit_register_tohost(sdev->service, hip4_smapper_refill_isr, hip); - control->fh_ind = - scsc_service_mifintrbit_alloc_fromhost(sdev->service, SCSC_MIFINTR_TARGET_R4); - - control->mbox_ptr = - scsc_mx_service_get_mbox_ptr(sdev->service, control->mbox_scb); - - /* All banks to REMAP and FW owner*/ - *control->mbox_ptr = 0x0; - - /* Update hip4 config table */ - hip->hip_control->config_v4.smapper_th_req = - control->th_req; - hip->hip_control->config_v4.smapper_fh_ind = - control->fh_ind; - hip->hip_control->config_v4.smapper_mbox_scb = - (u8)control->mbox_scb; - - for (i = RX_0; i < END_RX_BANKS; i++) { - u8 has_entries; - u8 bank; - - has_entries = hip->hip_priv->smapper_banks[i].entries; - if (has_entries) { - /* Get the bank index */ - bank = hip->hip_priv->smapper_banks[i].bank; - hip->hip_control->config_v4.smapper_bank_addr[bank] = scsc_service_mifsmapper_get_bank_base_address(sdev->service, bank); - hip->hip_control->config_v4.smapper_entries_banks[bank] = has_entries; - hip->hip_control->config_v4.smapper_pow_sz[bank] = 12; /* 4kB */ - } - } - return 0; -} - -void hip4_smapper_deinit(struct slsi_dev *sdev, struct slsi_hip4 *hip) -{ - struct hip4_smapper_bank *bank; - struct hip4_smapper_control *control; - unsigned long flags; - u8 i; - - SLSI_DBG4_NODEV(SLSI_SMAPPER, "SMAPPER deinit\n"); - control = &(hip->hip_priv->smapper_control); - - spin_lock_irqsave(&control->smapper_lock, flags); - for (i = RX_0; i < END_RX_BANKS; i++) { - bank = &hip->hip_priv->smapper_banks[i]; - bank->in_use = false; - hip4_smapper_free_skb_buffers(sdev, bank); - kfree(bank->skbuff_dma); - kfree(bank->skbuff); - scsc_service_mifsmapper_free_bank(sdev->service, bank->bank); - } - spin_unlock_irqrestore(&control->smapper_lock, flags); - - scsc_service_mifintrbit_unregister_tohost(sdev->service, control->th_req); - scsc_service_mifintrbit_free_fromhost(sdev->service, control->fh_ind, SCSC_MIFINTR_TARGET_R4); - scsc_service_free_mboxes(sdev->service, 1, control->mbox_scb); - -} diff --git a/drivers/net/wireless/scsc/hip4_smapper.h b/drivers/net/wireless/scsc/hip4_smapper.h deleted file mode 100644 index 92270116da72..000000000000 --- a/drivers/net/wireless/scsc/hip4_smapper.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __HIP4_SMAPPER_H__ -#define __HIP4_SMAPPER_H__ - -struct slsi_dev; -struct slsi_hip4; - -enum smapper_type { - TX_5G, - TX_2G, - RX -}; - -#define HIP4_SMAPPER_TOTAL_BANKS 10 - -#define HIP4_SMAPPER_BANK_SMALL false -#define HIP4_SMAPPER_BANK_LARGE true - -#define HIP_SMAPPER_OWNER_FW 0 -#define HIP_SMAPPER_OWNER_HOST 1 - -#define HIP_SMAPPER_STATUS_REFILL 0 -#define HIP_SMAPPER_STATUS_MAPPED 1 - -#define HIP4_SMAPPER_OTHER_CPU 0 -#define HIP4_SMAPPER_OWN_CPU 1 - -#define HIP4_SMAPPER_STATE_OUT 0 -#define HIP4_SMAPPER_STATE_WANT 1 -#define HIP4_SMAPPER_STATE_CLAIM 2 - -#define HIP4_SMAPPER_BANKS_CHECK_CONFIGURE(reg) (((reg) >> 30) == 0 ? 1 : 0) -#define HIP4_SMAPPER_BANKS_CONFIGURE_DONE(reg) ((reg) = (reg) | 0xc0000000) - -#define HIP4_SMAPPER_GET_BANK_STATE(b, reg) (((0x1 << ((b) * 2)) & (reg)) > 0 ? 1 : 0) -#define HIP4_SMAPPER_GET_BANK_OWNER(b, reg) (((0x2 << ((b) * 2)) & (reg)) > 0 ? 1 : 0) - -#define HIP4_SMAPPER_SET_BANK_STATE(b, reg, val) ((reg) = ((reg) & ~(0x1 << ((b) * 2))) | \ - ((val) << ((b) * 2))) -#define HIP4_SMAPPER_SET_BANK_OWNER(b, reg, val) ((reg) = (reg & ~(0x2 << ((b) * 2))) | \ - (((val) << 1) << ((b) * 2))) - - -struct hip4_smapper_descriptor { - u8 bank_num; - u8 entry_num; - u16 entry_size; - u16 headroom; -}; - -/* There should be an agreement between host and FW about bank mapping */ -/* TODO : think about this agreement */ -enum smapper_banks { - RX_0, - RX_1, - RX_2, - RX_3, - END_RX_BANKS -}; - -struct hip4_smapper_control { - u32 emul_loc; /* Smapper emulator location in MIF_ADDR */ - u32 emul_sz; /* Smapper emulator size */ - u8 th_req; /* TH smapper request interrupt bit position */ - u8 fh_ind; /* FH smapper ind interrupt bit position */ - u32 mbox_scb; /* SMAPPER MBOX scoreboard location */ - u32 *mbox_ptr; /* Mbox pointer */ - spinlock_t smapper_lock; - /* Lookup table to map the virtual bank mapping in wlan with the phy mapping in HW */ - /* Currently is safe to use this indexing as only WIFI is using smapper */ - u8 lookuptable[HIP4_SMAPPER_TOTAL_BANKS]; -}; - -struct hip4_smapper_bank { - enum smapper_type type; - u16 entries; - bool in_use; - u8 bank; - u8 cur; - u32 entry_size; - struct sk_buff **skbuff; - dma_addr_t *skbuff_dma; - struct hip4_smapper_control_entry *entry; - u16 align; -}; - -int hip4_smapper_init(struct slsi_dev *sdev, struct slsi_hip4 *hip); -void hip4_smapper_deinit(struct slsi_dev *sdev, struct slsi_hip4 *hip); - -struct mbulk *hip4_smapper_send(struct slsi_hip4 *hip, struct sk_buff *skb, int *val); -int hip4_smapper_consume_entry(struct slsi_dev *sdev, struct slsi_hip4 *hip, struct sk_buff *skb_fapi); -void *hip4_smapper_get_skb_data(struct slsi_dev *sdev, struct slsi_hip4 *hip, struct sk_buff *skb_fapi); -struct sk_buff *hip4_smapper_get_skb(struct slsi_dev *sdev, struct slsi_hip4 *hip, struct sk_buff *skb_fapi); -#endif diff --git a/drivers/net/wireless/scsc/hip_bh.h b/drivers/net/wireless/scsc/hip_bh.h deleted file mode 100644 index 1919d51cc9db..000000000000 --- a/drivers/net/wireless/scsc/hip_bh.h +++ /dev/null @@ -1,15 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_HIP_BH_H__ -#define __SLSI_HIP_BH_H__ - -#include "wl_result.h" - -CsrResult slsi_sdio_func_drv_register(void); -void slsi_sdio_func_drv_unregister(void); - -#endif /* __SLSI_HIP_BH_H__ */ diff --git a/drivers/net/wireless/scsc/ioctl.c b/drivers/net/wireless/scsc/ioctl.c deleted file mode 100755 index ff67a866a4cf..000000000000 --- a/drivers/net/wireless/scsc/ioctl.c +++ /dev/null @@ -1,2780 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "ioctl.h" -#include "debug.h" -#include "mlme.h" -#include "mgt.h" -#include "cac.h" -#include "hip.h" -#include "netif.h" -#include -#include -#include -#include "mib.h" -#include -#include -#include "dev.h" -#include "fapi.h" - -#define CMD_RXFILTERADD "RXFILTER-ADD" -#define CMD_RXFILTERREMOVE "RXFILTER-REMOVE" -#define CMD_RXFILTERSTART "RXFILTER-START" -#define CMD_RXFILTERSTOP "RXFILTER-STOP" -#define CMD_SETCOUNTRYREV "SETCOUNTRYREV" -#define CMD_GETCOUNTRYREV "GETCOUNTRYREV" -#define CMD_SETROAMTRIGGER "SETROAMTRIGGER" -#define CMD_GETROAMTRIGGER "GETROAMTRIGGER" -#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" -#define CMD_SETROAMDELTA "SETROAMDELTA" -#define CMD_GETROAMDELTA "GETROAMDELTA" -#define CMD_SETROAMSCANPERIOD "SETROAMSCANPERIOD" -#define CMD_GETROAMSCANPERIOD "GETROAMSCANPERIOD" -#define CMD_SETFULLROAMSCANPERIOD "SETFULLROAMSCANPERIOD" -#define CMD_GETFULLROAMSCANPERIOD "GETFULLROAMSCANPERIOD" -#define CMD_SETSCANCHANNELTIME "SETSCANCHANNELTIME" -#define CMD_GETSCANCHANNELTIME "GETSCANCHANNELTIME" -#define CMD_SETSCANNPROBES "SETSCANNPROBES" -#define CMD_GETSCANNPROBES "GETSCANNPROBES" -#define CMD_SETROAMMODE "SETROAMMODE" -#define CMD_GETROAMMODE "GETROAMMODE" -#define CMD_SETROAMINTRABAND "SETROAMINTRABAND" -#define CMD_GETROAMINTRABAND "GETROAMINTRABAND" -#define CMD_SETROAMBAND "SETROAMBAND" -#define CMD_GETROAMBAND "GETROAMBAND" -#define CMD_SETROAMSCANCONTROL "SETROAMSCANCONTROL" -#define CMD_GETROAMSCANCONTROL "GETROAMSCANCONTROL" -#define CMD_SETSCANHOMETIME "SETSCANHOMETIME" -#define CMD_GETSCANHOMETIME "GETSCANHOMETIME" -#define CMD_SETSCANHOMEAWAYTIME "SETSCANHOMEAWAYTIME" -#define CMD_GETSCANHOMEAWAYTIME "GETSCANHOMEAWAYTIME" -#define CMD_SETOKCMODE "SETOKCMODE" -#define CMD_GETOKCMODE "GETOKCMODE" -#define CMD_SETWESMODE "SETWESMODE" -#define CMD_GETWESMODE "GETWESMODE" -#define CMD_SET_PMK "SET_PMK" -#define CMD_HAPD_GET_CHANNEL "HAPD_GET_CHANNEL" -#define CMD_SET_SAP_CHANNEL_LIST "SET_SAP_CHANNEL_LIST" -#define CMD_REASSOC "REASSOC" -#define CMD_SETROAMSCANCHANNELS "SETROAMSCANCHANNELS" -#define CMD_GETROAMSCANCHANNELS "GETROAMSCANCHANNELS" -#define CMD_SENDACTIONFRAME "SENDACTIONFRAME" -#define CMD_HAPD_MAX_NUM_STA "HAPD_MAX_NUM_STA" -#define CMD_COUNTRY "COUNTRY" -#define CMD_SEND_GK "SEND_GK" -#define CMD_SETAPP2PWPSIE "SET_AP_P2P_WPS_IE" -#define CMD_P2PSETPS "P2P_SET_PS" -#define CMD_P2PSETNOA "P2P_SET_NOA" -#define CMD_P2PECSA "P2P_ECSA" -#define CMD_P2PLOSTART "P2P_LO_START" -#define CMD_P2PLOSTOP "P2P_LO_STOP" -#define CMD_TDLSCHANNELSWITCH "TDLS_CHANNEL_SWITCH" -#define CMD_SETROAMOFFLOAD "SETROAMOFFLOAD" -#define CMD_SETROAMOFFLAPLIST "SETROAMOFFLAPLIST" -#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE -#define CMD_SET_LATENCY_MODE "SET_LATENCY_MODE" -#define CMD_SET_POWER_MGMT "SET_POWER_MGMT" -#endif -#define CMD_SET_DISCONNECT_IES "SET_DISCONNECT_IES" - -#define CMD_SETBAND "SETBAND" -#define CMD_GETBAND "GETBAND" -#define CMD_SET_FCC_CHANNEL "SET_FCC_CHANNEL" - -#define CMD_FAKEMAC "FAKEMAC" - -#define CMD_GETBSSRSSI "GET_BSS_RSSI" -#define CMD_GETBSSINFO "GETBSSINFO" -#define CMD_GETSTAINFO "GETSTAINFO" -#define CMD_GETASSOCREJECTINFO "GETASSOCREJECTINFO" - -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -#define CMD_BEACON_RECV "BEACON_RECV" -#endif -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -#define CMD_SET_ENHANCED_ARP_TARGET "SET_ENHANCED_ARP_TARGET" -#define CMD_GET_ENHANCED_ARP_COUNTS "GET_ENHANCED_ARP_COUNTS" -#endif - -/* Known commands from framework for which no handlers */ -#define CMD_AMPDU_MPDU "AMPDU_MPDU" -#define CMD_BTCOEXMODE "BTCOEXMODE" -#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" -#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" -#define CMD_CHANGE_RL "CHANGE_RL" -#define CMD_INTERFACE_CREATE "INTERFACE_CREATE" -#define CMD_INTERFACE_DELETE "INTERFACE_DELETE" -#define CMD_SET_INDOOR_CHANNELS "SET_INDOOR_CHANNELS" -#define CMD_GET_INDOOR_CHANNELS "GET_INDOOR_CHANNELS" -#define CMD_LTECOEX "LTECOEX" -#define CMD_MIRACAST "MIRACAST" -#define CMD_RESTORE_RL "RESTORE_RL" -#define CMD_RPSMODE "RPSMODE" -#define CMD_SETCCXMODE "SETCCXMODE" -#define CMD_SETDFSSCANMODE "SETDFSSCANMODE" -#define CMD_SETJOINPREFER "SETJOINPREFER" -#define CMD_SETSINGLEANT "SETSINGLEANT" -#define CMD_SET_TX_POWER_CALLING "SET_TX_POWER_CALLING" - -#define CMD_DRIVERDEBUGDUMP "DEBUG_DUMP" -#define CMD_DRIVERDEBUGCOMMAND "DEBUG_COMMAND" -#define CMD_TESTFORCEHANG "SLSI_TEST_FORCE_HANG" -#define CMD_GETREGULATORY "GETREGULATORY" - -#define CMD_SET_TX_POWER_SAR "SET_TX_POWER_SAR" -#define CMD_GET_TX_POWER_SAR "GET_TX_POWER_SAR" - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER -#define CMD_ENHANCED_PKT_FILTER "ENHANCED_PKT_FILTER" -#endif -#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER -#define CMD_ABNORMAL_MULTICAST_PKT_FILTER "ABNORMAL_MULTICAST_PKT_FILTER" -#endif -#define CMD_GET_MAX_LINK_SPEED "GET_MAX_LINK_SPEED" - -#ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS -#define CMD_SET_NUM_ANTENNAS "SET_NUM_ANTENNAS" -#endif - -#define ROAMOFFLAPLIST_MIN 1 -#define ROAMOFFLAPLIST_MAX 100 - -static int slsi_parse_hex(unsigned char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return 0; -} - -static void slsi_machexstring_to_macarray(char *mac_str, u8 *mac_arr) -{ - mac_arr[0] = slsi_parse_hex(mac_str[0]) << 4 | slsi_parse_hex(mac_str[1]); - mac_arr[1] = slsi_parse_hex(mac_str[3]) << 4 | slsi_parse_hex(mac_str[4]); - mac_arr[2] = slsi_parse_hex(mac_str[6]) << 4 | slsi_parse_hex(mac_str[7]); - mac_arr[3] = slsi_parse_hex(mac_str[9]) << 4 | slsi_parse_hex(mac_str[10]); - mac_arr[4] = slsi_parse_hex(mac_str[12]) << 4 | slsi_parse_hex(mac_str[13]); - mac_arr[5] = slsi_parse_hex(mac_str[15]) << 4 | slsi_parse_hex(mac_str[16]); -} - -static ssize_t slsi_set_suspend_mode(struct net_device *dev, char *command) -{ - int vif; - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct slsi_dev *sdev = netdev_vif->sdev; - int user_suspend_mode; - int previous_suspend_mode; - u8 host_state; - int ret = 0; - - user_suspend_mode = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0'; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - previous_suspend_mode = sdev->device_config.user_suspend_mode; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - if (user_suspend_mode != previous_suspend_mode) { - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (vif = 1; vif <= CONFIG_SCSC_WLAN_MAX_INTERFACES; vif++) { - struct net_device *dev = slsi_get_netdev_locked(sdev, vif); - struct netdev_vif *ndev_vif; - - if (!dev) - continue; - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if ((ndev_vif->activated) && - (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - if (user_suspend_mode) - ret = slsi_update_packet_filters(sdev, dev); - else - ret = slsi_clear_packet_filters(sdev, dev); - if (ret != 0) - SLSI_NET_ERR(dev, "Error in updating /clearing the packet filters,ret=%d", ret); - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - } - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - sdev->device_config.user_suspend_mode = user_suspend_mode; - host_state = sdev->device_config.host_state; - - if (!sdev->device_config.user_suspend_mode) - host_state = host_state | SLSI_HOSTSTATE_LCD_ACTIVE; - else - host_state = host_state & ~SLSI_HOSTSTATE_LCD_ACTIVE; - sdev->device_config.host_state = host_state; - - ret = slsi_mlme_set_host_state(sdev, dev, host_state); - if (ret != 0) - SLSI_NET_ERR(dev, "Error in setting the Host State, ret=%d", ret); - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return ret; -} - -static ssize_t slsi_set_p2p_oppps(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif; - struct slsi_dev *sdev; - u8 *p2p_oppps_param = NULL; - int offset = 0; - unsigned int ct_param; - unsigned int legacy_ps; - unsigned int opp_ps; - int readbyte = 0; - int result = 0; - - p2p_oppps_param = command + strlen(CMD_P2PSETPS) + 1; - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - /* The NOA param shall be added only after P2P-VIF is active */ - if ((!ndev_vif->activated) || (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO)) { - SLSI_ERR_NODEV("P2P GO vif not activated\n"); - result = -EINVAL; - goto exit; - } - - sdev = ndev_vif->sdev; - readbyte = slsi_str_to_int(&p2p_oppps_param[offset], &legacy_ps); - if (!readbyte) { - SLSI_ERR(sdev, "ct_param: failed to read legacy_ps\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - - readbyte = slsi_str_to_int(&p2p_oppps_param[offset], &opp_ps); - if (!readbyte) { - SLSI_ERR(sdev, "ct_param: failed to read ct_param\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - - readbyte = slsi_str_to_int(&p2p_oppps_param[offset], &ct_param); - if (!readbyte) { - SLSI_ERR(sdev, "ct_param: failed to read ct_param\n"); - result = -EINVAL; - goto exit; - } - - if (opp_ps == 0) - result = slsi_mlme_set_ctwindow(sdev, dev, opp_ps); - else if (ct_param < (unsigned int)ndev_vif->ap.beacon_interval) - result = slsi_mlme_set_ctwindow(sdev, dev, ct_param); - else - SLSI_DBG1(sdev, SLSI_CFG80211, "p2p ct window = %d is out of range for beacon interval(%d)\n", ct_param, ndev_vif->ap.beacon_interval); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return result; -} - -static ssize_t slsi_p2p_set_noa_params(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif; - struct slsi_dev *sdev; - int result = 0; - u8 *noa_params = NULL; - int offset = 0; - int readbyte = 0; - unsigned int noa_count; - unsigned int duration; - unsigned int interval; - - noa_params = command + strlen(CMD_P2PSETNOA) + 1; - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - /* The NOA param shall be added only after P2P-VIF is active */ - if ((!ndev_vif->activated) || (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO)) { - SLSI_ERR_NODEV("P2P GO vif not activated\n"); - result = -EINVAL; - goto exit; - } - - sdev = ndev_vif->sdev; - readbyte = slsi_str_to_int(&noa_params[offset], &noa_count); - if (!readbyte) { - SLSI_ERR(sdev, "noa_count: failed to read a numeric value\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - - readbyte = slsi_str_to_int(&noa_params[offset], &interval); - if (!readbyte) { - SLSI_ERR(sdev, "interval: failed to read a numeric value\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - - readbyte = slsi_str_to_int(&noa_params[offset], &duration); - if (!readbyte) { - SLSI_ERR(sdev, "duration: failed to read a numeric value, at offset(%d)\n", offset); - result = -EINVAL; - goto exit; - } - - /* Skip start time */ - result = slsi_mlme_set_p2p_noa(sdev, dev, noa_count, interval, duration); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return result; -} - -static ssize_t slsi_p2p_ecsa(struct net_device *dev, char *command) -{ - struct netdev_vif *ndev_vif; - struct netdev_vif *group_dev_vif; - struct slsi_dev *sdev; - struct net_device *group_dev = NULL; - int result = 0; - u8 *ecsa_params = NULL; - int offset = 0; - int readbyte = 0; - unsigned int channel; - unsigned int bandwidth; - u16 center_freq = 0; - u16 chan_info = 0; - struct cfg80211_chan_def chandef; - enum nl80211_band band; - enum nl80211_channel_type chan_type = NL80211_CHAN_NO_HT; - - ecsa_params = command + strlen(CMD_P2PECSA) + 1; - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - sdev = ndev_vif->sdev; - group_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN); - if (!group_dev) { - SLSI_INFO(sdev, "No Group net_dev found\n"); - return -EINVAL; - } - readbyte = slsi_str_to_int(&ecsa_params[offset], &channel); - if (!readbyte) { - SLSI_ERR(sdev, "channel: failed to read a numeric value\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - readbyte = slsi_str_to_int(&ecsa_params[offset], &bandwidth); - if (!readbyte) { - SLSI_ERR(sdev, "bandwidth: failed to read a numeric value\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; - center_freq = ieee80211_channel_to_frequency(channel, band); - SLSI_DBG1(sdev, SLSI_CFG80211, "p2p ecsa_params (center_freq)= (%d)\n", center_freq); - chandef.chan = ieee80211_get_channel(sdev->wiphy, center_freq); - chandef.width = (band == NL80211_BAND_2GHZ) ? NL80211_CHAN_WIDTH_20_NOHT : NL80211_CHAN_WIDTH_80; - -#ifndef SSB_4963_FIXED - /* Default HT40 configuration */ - if (sdev->band_5g_supported) { - if (bandwidth == 80) { - chandef.width = NL80211_CHAN_WIDTH_40; - bandwidth = 40; - if (channel == 36 || channel == 44 || channel == 149 || channel == 157) - chan_type = NL80211_CHAN_HT40PLUS; - else - chan_type = NL80211_CHAN_HT40MINUS; - } - } -#endif - if (channel == 165 && bandwidth != 20) { - bandwidth = 20; - chan_type = NL80211_CHAN_HT20; - } - cfg80211_chandef_create(&chandef, chandef.chan, chan_type); - chan_info = slsi_get_chann_info(sdev, &chandef); - if (bandwidth != 20) - center_freq = slsi_get_center_freq1(sdev, chan_info, center_freq); - group_dev_vif = netdev_priv(group_dev); - SLSI_MUTEX_LOCK(group_dev_vif->vif_mutex); - result = slsi_mlme_channel_switch(sdev, group_dev, center_freq, chan_info); - SLSI_MUTEX_UNLOCK(group_dev_vif->vif_mutex); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return result; -} - -static ssize_t slsi_ap_vendor_ies_write(struct slsi_dev *sdev, struct net_device *dev, u8 *ie, - size_t ie_len, u16 purpose) -{ - u8 *vendor_ie = NULL; - int result = 0; - struct netdev_vif *ndev_vif; - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - /* During AP start before mlme_start_req, supplicant calls set_ap_wps_ie() to send the vendor IEs for each - * beacon, probe response and association response. As we get all of them in mlme_start_req, ignoring the - * same which comes before adding GO VIF - */ - if (!ndev_vif->activated) { - SLSI_DBG1(sdev, SLSI_CFG80211, "vif not activated\n"); - result = 0; - goto exit; - } - if (!(ndev_vif->iftype == NL80211_IFTYPE_P2P_GO || ndev_vif->iftype == NL80211_IFTYPE_AP)) { - SLSI_ERR(sdev, "Not AP or P2P interface. interfaceType:%d\n", ndev_vif->iftype); - result = -EINVAL; - goto exit; - } - - vendor_ie = kmalloc(ie_len, GFP_KERNEL); - if (!vendor_ie) { - SLSI_ERR(sdev, "kmalloc failed\n"); - result = -ENOMEM; - goto exit; - } - memcpy(vendor_ie, ie, ie_len); - - slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - result = slsi_ap_prepare_add_info_ies(ndev_vif, vendor_ie, ie_len); - - if (result == 0) - result = slsi_mlme_add_info_elements(sdev, dev, purpose, ndev_vif->ap.add_info_ies, ndev_vif->ap.add_info_ies_len); - - slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - kfree(vendor_ie); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return result; -} - -static ssize_t slsi_set_ap_p2p_wps_ie(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int readbyte = 0; - int offset = 0; - int result = 0; - enum if_type { - IF_TYPE_NONE, - IF_TYPE_P2P_DEVICE, - IF_TYPE_AP_P2P - } iftype = IF_TYPE_NONE; - enum frame_type { - FRAME_TYPE_NONE, - FRAME_TYPE_BEACON, - FRAME_TYPE_PROBE_RESPONSE, - FRAME_TYPE_ASSOC_RESPONSE - } frametype = FRAME_TYPE_NONE; - u8 *params = command + strlen(CMD_SETAPP2PWPSIE) + 1; - int params_len = buf_len - strlen(CMD_SETAPP2PWPSIE) - 1; - - readbyte = slsi_str_to_int(¶ms[offset], (int *)&frametype); - if (!readbyte) { - SLSI_ERR(sdev, "frametype: failed to read a numeric value\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - readbyte = slsi_str_to_int(¶ms[offset], (int *)&iftype); - if (!readbyte) { - SLSI_ERR(sdev, "iftype: failed to read a numeric value\n"); - result = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - params_len = params_len - offset; - - SLSI_NET_DBG2(dev, SLSI_NETDEV, - "command=%s, frametype=%d, iftype=%d, total buf_len=%d, params_len=%d\n", - command, frametype, iftype, buf_len, params_len); - - /* check the net device interface type */ - if (iftype == IF_TYPE_P2P_DEVICE) { - u8 *probe_resp_ie = NULL; /* params+offset; */ - - if (frametype != FRAME_TYPE_PROBE_RESPONSE) { - SLSI_NET_ERR(dev, "Wrong frame type received\n"); - goto exit; - } - probe_resp_ie = kmalloc(params_len, GFP_KERNEL); - if (probe_resp_ie == NULL) { - SLSI_ERR(sdev, "Malloc for IEs failed\n"); - return -ENOMEM; - } - - memcpy(probe_resp_ie, params+offset, params_len); - - return slsi_p2p_dev_probe_rsp_ie(sdev, dev, probe_resp_ie, params_len); - } else if (iftype == IF_TYPE_AP_P2P) { - if (frametype == FRAME_TYPE_BEACON) - return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len, FAPI_PURPOSE_BEACON); - else if (frametype == FRAME_TYPE_PROBE_RESPONSE) - return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len, - FAPI_PURPOSE_PROBE_RESPONSE); - else if (frametype == FRAME_TYPE_ASSOC_RESPONSE) - return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len, - FAPI_PURPOSE_ASSOCIATION_RESPONSE); - } -exit: - return result; -} - -/** - * P2P_LO_START handling. - * Add unsync vif, register for action frames and set the listen channel. - * The probe response IEs would be configured later. - */ -static int slsi_p2p_lo_start(struct net_device *dev, char *command) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct ieee80211_channel *chan = NULL; - char *lo_params = NULL; - unsigned int channel, duration, interval, count; - int ret = 0; - int freq; - int readbyte = 0; - enum nl80211_band band; - int offset = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - /* Reject LO if other operations are in progress. Back to back LO can be received. - * In such a case, if state is Listening then the listen offload flag should be true else - * reject the request as the Listening state would then be due to ROC. - */ - if ((sdev->p2p_state == P2P_SCANNING) || (sdev->p2p_state > P2P_LISTENING) || - ((sdev->p2p_state == P2P_LISTENING) && (!ndev_vif->unsync.listen_offload))) { - SLSI_NET_ERR(dev, "Reject LO due to ongoing P2P operation (state: %s)\n", slsi_p2p_state_text(sdev->p2p_state)); - ret = -EINVAL; - goto exit; - } - - lo_params = command + strlen(CMD_P2PLOSTART) + 1; - readbyte = slsi_str_to_int(&lo_params[offset], &channel); - if (!readbyte) { - SLSI_ERR(sdev, "channel: failed to read a numeric value\n"); - ret = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - readbyte = slsi_str_to_int(&lo_params[offset], &duration); - if (!readbyte) { - SLSI_ERR(sdev, "duration: failed to read a numeric value\n"); - ret = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - readbyte = slsi_str_to_int(&lo_params[offset], &interval); - if (!readbyte) { - SLSI_ERR(sdev, "interval: failed to read a numeric value\n"); - ret = -EINVAL; - goto exit; - } - offset = offset + readbyte + 1; - readbyte = slsi_str_to_int(&lo_params[offset], &count); - if (!readbyte) { - SLSI_ERR(sdev, "count: failed to read a numeric value\n"); - ret = -EINVAL; - goto exit; - } - - if (!ndev_vif->activated) { - ret = slsi_mlme_add_vif(sdev, dev, dev->dev_addr, dev->dev_addr); - if (ret != 0) { - SLSI_NET_ERR(dev, "Unsync vif addition failed\n"); - goto exit; - } - - ndev_vif->activated = true; - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE); - - ret = slsi_mlme_register_action_frame(sdev, dev, SLSI_ACTION_FRAME_PUBLIC, SLSI_ACTION_FRAME_PUBLIC); - if (ret != 0) { - SLSI_NET_ERR(dev, "Action frame registration for unsync vif failed\n"); - goto exit_with_vif_deactivate; - } - } - - /* Send set_channel irrespective of the values of LO parameters as they are not cached - * in driver to check whether they have changed. - */ - band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; - freq = ieee80211_channel_to_frequency(channel, band); - chan = ieee80211_get_channel(sdev->wiphy, freq); - if (!chan) { - SLSI_NET_ERR(dev, "Incorrect channel: %u - Listen Offload failed\n", channel); - ret = -EINVAL; - goto exit_with_vif_deactivate; - } - - ret = slsi_mlme_set_channel(sdev, dev, chan, duration, interval, count); - if (ret != 0) { - SLSI_NET_ERR(dev, "Set channel for unsync vif failed\n"); - goto exit_with_vif_deactivate; - } else { - ndev_vif->chan = chan; - ndev_vif->driver_channel = chan->hw_value; - } - /* If framework sends the values for listen offload as 1,500,5000 and 6, - * where 5000ms (5 seconds) is the listen interval which needs to be repeated - * 6 times(i.e. count). Hence listen_end_ind comes after 30 seconds - * (6 * 5000 = 30000ms) Hence host should wait 31 seconds to delete the - * unsync VIF for one such P2P listen offload request. - */ - slsi_p2p_queue_unsync_vif_del_work(ndev_vif, interval * count + 1000); - ndev_vif->unsync.listen_offload = true; - SLSI_P2P_STATE_CHANGE(ndev_vif->sdev, P2P_LISTENING); - goto exit; - -exit_with_vif_deactivate: - slsi_p2p_vif_deactivate(sdev, dev, true); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return ret; -} - -/** - * P2P_LO_STOP handling. - * Clear listen offload flag. - * Delete the P2P unsynchronized vif. - */ -static int slsi_p2p_lo_stop(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - WARN_ON((!ndev_vif->unsync.listen_offload) || (ndev_vif->sdev->p2p_state != P2P_LISTENING)); - - ndev_vif->unsync.listen_offload = false; - - /* Deactivating the p2p unsynchronized vif */ - if (ndev_vif->sdev->p2p_state == P2P_LISTENING) - slsi_p2p_vif_deactivate(ndev_vif->sdev, ndev_vif->wdev.netdev, true); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return 0; -} - -static ssize_t slsi_rx_filter_num_write(struct net_device *dev, int add_remove, int filter_num) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int ret = 0; - - if (add_remove) - sdev->device_config.rx_filter_num = filter_num; - else - sdev->device_config.rx_filter_num = 0; - return ret; -} - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if !defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION < 90000) -static ssize_t slsi_create_interface(struct net_device *dev, char *intf_name) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct net_device *ap_dev; - - ap_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN); - if (ap_dev && (strcmp(ap_dev->name, intf_name) == 0)) { - SLSI_NET_ERR(dev, "%s already created\n", intf_name); - return -EINVAL; - } - - ap_dev = slsi_dynamic_interface_create(sdev->wiphy, intf_name, NL80211_IFTYPE_AP, NULL); - if (ap_dev) { - sdev->netdev_ap = ap_dev; - return 0; - } - - SLSI_NET_ERR(dev, "Failed to create AP interface %s\n", intf_name); - return -EINVAL; -} - -static ssize_t slsi_delete_interface(struct net_device *dev, char *intf_name) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - - if (strcmp(intf_name, CONFIG_SCSC_AP_INTERFACE_NAME) == 0) - dev = sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]; - - if (!dev) { - SLSI_WARN(sdev, "AP dev is NULL"); - return -EINVAL; - } - ndev_vif = netdev_priv(dev); - - if (ndev_vif->activated) - slsi_stop_net_dev(sdev, dev); - slsi_netif_remove_rtlnl_locked(sdev, dev); - - sdev->netdev_ap = NULL; - SLSI_DBG1_NODEV(SLSI_MLME, "Successfully deleted AP interface %s ", intf_name); - - return 0; -} -#endif - -static ssize_t slsi_set_indoor_channels(struct net_device *dev, char *arg) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int readbyte = 0; - int offset = 0; - int res; - int ret; - - readbyte = slsi_str_to_int(&arg[offset], &res); - - ret = slsi_set_mib_wifi_sharing_5ghz_channel(sdev, SLSI_PSID_UNIFI_WI_FI_SHARING5_GHZ_CHANNEL, - res, offset, readbyte, arg); - - return ret; -} - -static ssize_t slsi_get_indoor_channels(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - char op[150] = ""; - char int_string[30] = ""; - int i; - int len = 0; - - SLSI_DBG1_NODEV(SLSI_MLME, "GET_INDOOR_CHANNELS : %d ", sdev->num_5g_restricted_channels); - - for (i = 0; i < sdev->num_5g_restricted_channels; i++) { - sprintf(int_string, "%d", sdev->wifi_sharing_5g_restricted_channels[i]); - strcat(op, int_string); - strcat(op, " "); - } - - len = snprintf(command, buf_len, "%d %s", sdev->num_5g_restricted_channels, op); - - return len; -} -#endif -static ssize_t slsi_set_country_rev(struct net_device *dev, char *country_code) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - char alpha2_rev[4]; - int status = 0; - - if (!country_code) - return -EINVAL; - - memcpy(alpha2_rev, country_code, 4); - - status = slsi_set_country_update_regd(sdev, alpha2_rev, 4); - - return status; -} - -static ssize_t slsi_get_country_rev(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - u8 buf[5]; - int len = 0; - - memset(buf, 0, sizeof(buf)); - - len = snprintf(command, buf_len, "%s %c%c %d", CMD_GETCOUNTRYREV, - sdev->device_config.domain_info.regdomain->alpha2[0], - sdev->device_config.domain_info.regdomain->alpha2[1], - sdev->device_config.domain_info.regdomain->dfs_region); - - return len; -} - -#ifdef CONFIG_SCSC_WLAN_WES_NCHO -static ssize_t slsi_roam_scan_trigger_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_RSSI_ROAM_SCAN_TRIGGER, mib_value); -} - -static ssize_t slsi_roam_scan_trigger_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_RSSI_ROAM_SCAN_TRIGGER, &mib_value); - if (res) - return res; - res = snprintf(command, buf_len, "%s %d", CMD_GETROAMTRIGGER, mib_value); - return res; -} - -static ssize_t slsi_roam_delta_trigger_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_DELTA_TRIGGER, mib_value); -} - -static ssize_t slsi_roam_delta_trigger_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_DELTA_TRIGGER, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETROAMDELTA, mib_value); - return res; -} - -static ssize_t slsi_cached_channel_scan_period_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_CACHED_CHANNEL_SCAN_PERIOD, mib_value * 1000000); -} - -static ssize_t slsi_cached_channel_scan_period_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_CACHED_CHANNEL_SCAN_PERIOD, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETROAMSCANPERIOD, mib_value / 1000000); - - return res; -} - -static ssize_t slsi_full_roam_scan_period_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_FULL_ROAM_SCAN_PERIOD, mib_value * 1000000); -} - -static ssize_t slsi_full_roam_scan_period_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_FULL_ROAM_SCAN_PERIOD, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETFULLROAMSCANPERIOD, mib_value / 1000000); - - return res; -} - -static ssize_t slsi_roam_scan_max_active_channel_time_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_MAX_ACTIVE_CHANNEL_TIME, mib_value); -} - -static ssize_t slsi_roam_scan_max_active_channel_time_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_MAX_ACTIVE_CHANNEL_TIME, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETSCANCHANNELTIME, mib_value); - - return res; -} - -static ssize_t slsi_roam_scan_probe_interval_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_NPROBE, mib_value); -} - -static ssize_t slsi_roam_scan_probe_interval_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_NPROBE, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETSCANNPROBES, mib_value); - - return res; -} - -static ssize_t slsi_roam_mode_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - if (slsi_is_rf_test_mode_enabled()) { - SLSI_DBG1_NODEV(SLSI_MLME, "SLSI_PSID_UNIFI_ROAM_MODE is not supported because of rf test mode.\n"); - return -ENOTSUPP; - } - - slsi_str_to_int(command, &mib_value); - - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_MODE, mib_value); -} - -static ssize_t slsi_roam_mode_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_MODE, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETROAMMODE, mib_value); - - return res; -} - -static int slsi_roam_offload_ap_list(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct cfg80211_acl_data *mac_acl; - int ap_count = 0; - int buf_pos = 0; - int i, r; - int malloc_len; - - /* command format: - * x,aa:bb:cc:dd:ee:ff,xx:yy:zz:qq:ww:ee... - * x = 1 to 100 - * each mac address id 17 bytes and every mac address is separated by ',' - */ - buf_pos = slsi_str_to_int(command, &ap_count); - if (ap_count < ROAMOFFLAPLIST_MIN || ap_count > ROAMOFFLAPLIST_MAX) { - SLSI_ERR(sdev, "ap_count: %d\n", ap_count); - return -EINVAL; - } - buf_pos++; - /* each mac address takes 18 bytes(17 for mac address and 1 for ',') except the last one. - * the last mac address is just 17 bytes(without a coma) - */ - if ((buf_len - buf_pos) < (ap_count*18 - 1)) { - SLSI_ERR(sdev, "Invalid buff len:%d for %d APs\n", (buf_len - buf_pos), ap_count); - return -EINVAL; - } - malloc_len = sizeof(struct cfg80211_acl_data) + sizeof(struct mac_address) * ap_count; - mac_acl = kmalloc(malloc_len, GFP_KERNEL); - if (!mac_acl) { - SLSI_ERR(sdev, "MEM fail for size:%ld\n", sizeof(struct cfg80211_acl_data) + sizeof(struct mac_address) * ap_count); - return -ENOMEM; - } - - for (i = 0; i < ap_count; i++) { - slsi_machexstring_to_macarray(&command[buf_pos], mac_acl->mac_addrs[i].addr); - buf_pos += 18; - SLSI_DBG3_NODEV(SLSI_MLME, "[%pM]", mac_acl->mac_addrs[i].addr); - } - mac_acl->acl_policy = NL80211_ACL_POLICY_DENY_UNLESS_LISTED; - mac_acl->n_acl_entries = ap_count; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - r = slsi_mlme_set_acl(sdev, dev, ndev_vif->ifnum, mac_acl); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - kfree(mac_acl); - return r; -} - -static ssize_t slsi_roam_scan_band_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_BAND, mib_value); -} - -static ssize_t slsi_roam_scan_band_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_BAND, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETROAMINTRABAND, mib_value); - - return res; -} - -static ssize_t slsi_freq_band_write(struct net_device *dev, uint band) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - - slsi_band_update(sdev, band); - /* Convert to correct Mib value (intra_band:1, all_band:2) */ - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_BAND, (band == SLSI_FREQ_BAND_AUTO) ? 2 : 1); -} - -static ssize_t slsi_freq_band_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - memset(buf, '\0', 128); - pos += scnprintf(buf + pos, bufsz - pos, "Band %d", sdev->device_config.supported_band); - - buf[pos] = '\0'; - memcpy(command, buf, pos + 1); - - return pos; -} - -static ssize_t slsi_roam_scan_control_write(struct net_device *dev, int mode) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - - if (mode == 0 || mode == 1) { - sdev->device_config.roam_scan_mode = mode; - } else { - SLSI_ERR(sdev, "Invalid roam Mode: Must be 0 or, 1 Not '%c'\n", mode); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return -EINVAL; - } - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_CONTROL, sdev->device_config.roam_scan_mode); -} - -static ssize_t slsi_roam_scan_control_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_CONTROL, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETROAMSCANCONTROL, mib_value); - - return res; -} - -static ssize_t slsi_roam_scan_home_time_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_TIME, mib_value); -} - -static ssize_t slsi_roam_scan_home_time_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_TIME, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETSCANHOMETIME, mib_value); - - return res; -} - -static ssize_t slsi_roam_scan_home_away_time_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - - slsi_str_to_int(command, &mib_value); - return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_AWAY_TIME, mib_value); -} - -static ssize_t slsi_roam_scan_home_away_time_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mib_value = 0; - int res; - - res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_AWAY_TIME, &mib_value); - if (res) - return res; - - res = snprintf(command, buf_len, "%s %d", CMD_GETSCANHOMEAWAYTIME, mib_value); - - return res; -} - -static ssize_t slsi_roam_scan_channels_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int result = 0; - int i, channel_count; - int offset = 0; - int readbyte = 0; - int channels[MAX_CHANNEL_LIST]; - - readbyte = slsi_str_to_int(command, &channel_count); - - if (!readbyte) { - SLSI_ERR(sdev, "channel count: failed to read a numeric value"); - return -EINVAL; - } - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - - if (channel_count > MAX_CHANNEL_LIST) - channel_count = MAX_CHANNEL_LIST; - sdev->device_config.wes_roam_scan_list.n = channel_count; - - for (i = 0; i < channel_count; i++) { - offset = offset + readbyte + 1; - readbyte = slsi_str_to_int(&command[offset], &channels[i]); - if (!readbyte) { - SLSI_ERR(sdev, "failed to read a numeric value\n"); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return -EINVAL; - } - - sdev->device_config.wes_roam_scan_list.channels[i] = channels[i]; - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - result = slsi_mlme_set_cached_channels(sdev, dev, channel_count, sdev->device_config.wes_roam_scan_list.channels); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return result; -} - -static ssize_t slsi_roam_scan_channels_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - char channel_buf[128] = { 0 }; - int pos = 0; - int i; - int channel_count = 0; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - channel_count = sdev->device_config.wes_roam_scan_list.n; - pos = scnprintf(channel_buf, sizeof(channel_buf), "%s %d", CMD_GETROAMSCANCHANNELS, channel_count); - for (i = 0; i < channel_count; i++) - pos += scnprintf(channel_buf + pos, sizeof(channel_buf) - pos, " %d", sdev->device_config.wes_roam_scan_list.channels[i]); - channel_buf[pos] = '\0'; - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - memcpy(command, channel_buf, pos + 1); - - return pos; -} - -static ssize_t slsi_okc_mode_write(struct net_device *dev, int mode) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - - if (mode == 0 || mode == 1) { - sdev->device_config.okc_mode = mode; - } else { - SLSI_ERR(sdev, "Invalid OKC Mode: Must be 0 or, 1 Not '%c'\n", mode); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return -EINVAL; - } - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return 0; -} - -static ssize_t slsi_okc_mode_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int okc_mode; - int res; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - okc_mode = sdev->device_config.okc_mode; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - res = snprintf(command, buf_len, "%s %d", CMD_GETOKCMODE, okc_mode); - - return res; -} - -static ssize_t slsi_wes_mode_write(struct net_device *dev, int mode) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int result = 0; - u32 action_frame_bmap = SLSI_STA_ACTION_FRAME_BITMAP; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - - if (mode == 0 || mode == 1) { - sdev->device_config.wes_mode = mode; - } else { - SLSI_ERR(sdev, "Invalid WES Mode: Must be 0 or 1 Not '%c'\n", mode); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return -EINVAL; - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((ndev_vif->activated) && (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - if (sdev->device_config.wes_mode) - action_frame_bmap |= SLSI_ACTION_FRAME_VENDOR_SPEC; - - result = slsi_mlme_register_action_frame(sdev, dev, action_frame_bmap, action_frame_bmap); - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return result; -} - -static ssize_t slsi_wes_mode_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int wes_mode; - int res; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - wes_mode = sdev->device_config.wes_mode; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - res = snprintf(command, buf_len, "%s %d", CMD_GETWESMODE, wes_mode); - - return res; -} -#endif - -static ssize_t slsi_set_pmk(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - u8 pmk[33]; - int result = 0; - - memcpy((u8 *)pmk, command + strlen("SET_PMK "), 32); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - result = slsi_mlme_set_pmk(sdev, dev, pmk, 32); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return result; -} - -static ssize_t slsi_auto_chan_read(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int ap_auto_chan; - int result = 0; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - ap_auto_chan = sdev->device_config.ap_auto_chan; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - result = snprintf(command, buf_len, "%d\n", ap_auto_chan); - return result; -} - -static ssize_t slsi_auto_chan_write(struct net_device *dev, char *command) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int n_channels; - struct ieee80211_channel *channels[SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - int count_channels; - int offset; - int chan; - int index = 0; -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - struct net_device *sta_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - struct netdev_vif *ndev_sta_vif = netdev_priv(sta_dev); - int sta_frequency; -#endif - - offset = slsi_str_to_int(&command[index], &n_channels); - if (!offset) { - SLSI_ERR(sdev, "channel count: failed to read a numeric value"); - return -EINVAL; - } - - if (n_channels > SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX) { - SLSI_ERR(sdev, "channel count:%d > SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX:%d\n", n_channels, SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX); - return -EINVAL; - } - - /* If "1 6 11" are passed, scan all "1 - 14" channels. If "1 6" are passed, scan "1 - 9" channels */ - if (n_channels == 3) - n_channels = 14; - else if (n_channels == 2) - n_channels = 9; - count_channels = 0; - for (chan = 1; chan <= n_channels; chan++) { - int center_freq; - - center_freq = ieee80211_channel_to_frequency(chan, NL80211_BAND_2GHZ); - channels[count_channels] = ieee80211_get_channel(sdev->wiphy, center_freq); - if (!channels[count_channels]) - SLSI_WARN(sdev, "channel number:%d invalid\n", chan); - else - count_channels++; - - } - - SLSI_DBG3(sdev, SLSI_INIT_DEINIT, "Number of channels for autochannel selection= %d", count_channels); - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - sdev->device_config.ap_auto_chan = 0; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -if ((ndev_sta_vif->activated) && (ndev_sta_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTING || - ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - sta_frequency = ndev_sta_vif->chan->center_freq; - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - if ((sta_frequency / 1000) == 2) - sdev->device_config.ap_auto_chan = ieee80211_frequency_to_channel(sta_frequency); - else - sdev->device_config.ap_auto_chan = 1; - SLSI_INFO(sdev, "Channel selected = %d", sdev->device_config.ap_auto_chan); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return 0; -} -#endif /*wifi sharing*/ - return slsi_auto_chan_select_scan(sdev, count_channels, channels); -} - -static ssize_t slsi_reassoc_write(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - u8 bssid[6] = { 0 }; - int channel; - int freq; - enum nl80211_band band = NL80211_BAND_2GHZ; - int r = 0; - - if (command[17] != ' ') { - SLSI_ERR(sdev, "Invalid Format '%s' '%c'\n", command, command[17]); - return -EINVAL; - } - - command[17] = '\0'; - - slsi_machexstring_to_macarray(command, bssid); - - if (!slsi_str_to_int(&command[18], &channel)) { - SLSI_ERR(sdev, "Invalid channel string: '%s'\n", &command[18]); - return -EINVAL; - } - - if (channel > 14) - band = NL80211_BAND_5GHZ; - freq = (u16)ieee80211_channel_to_frequency(channel, band); - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - r = slsi_mlme_roam(sdev, dev, bssid, freq); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -static ssize_t slsi_send_action_frame(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - char *temp; - u8 bssid[6] = { 0 }; - int channel = 0; - int freq = 0; - enum nl80211_band band = NL80211_BAND_2GHZ; - int r = 0; - u16 host_tag = slsi_tx_mgmt_host_tag(sdev); - u32 dwell_time; - struct ieee80211_hdr *hdr; - u8 *buf = NULL; - u8 *final_buf = NULL; - u8 temp_byte; - int len = 0; - int final_length = 0; - int i = 0, j = 0; - char *pos; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_ERR(sdev, "Not a STA vif or status is not CONNECTED\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - command[17] = '\0'; - slsi_machexstring_to_macarray(command, bssid); - - command[17] = ' '; - pos = strchr(command, ' '); - if (pos == NULL) - return -EINVAL; - *pos++ = '\0'; - - if (!slsi_str_to_int(pos, &channel)) { - SLSI_ERR(sdev, "Invalid channel string: '%s'\n", pos); - return -EINVAL; - } - pos++; - - if (channel > 14) - band = NL80211_BAND_5GHZ; - freq = (u16)ieee80211_channel_to_frequency(channel, band); - - pos = strchr(pos, ' '); - if (pos == NULL) - return -EINVAL; - *pos++ = '\0'; - - if (!slsi_str_to_int(pos, &dwell_time)) { - SLSI_ERR(sdev, "Invalid dwell time string: '%s'\n", pos); - return -EINVAL; - } - - pos = strchr(pos, ' '); - if (pos == NULL) - return -EINVAL; - pos++; - - /*Length of data*/ - temp = pos; - while (*temp != '\0') - temp++; - len = temp - pos; - - if (len <= 0) - return -EINVAL; - buf = kmalloc((len + 1) / 2, GFP_KERNEL); - - if (buf == NULL) { - SLSI_ERR(sdev, "Malloc failed\n"); - return -ENOMEM; - } - /*We receive a char buffer, convert to hex*/ - temp = pos; - for (i = 0, j = 0; j < len; j += 2) { - if (j + 1 == len) - temp_byte = slsi_parse_hex(temp[j]); - else - temp_byte = slsi_parse_hex(temp[j]) << 4 | slsi_parse_hex(temp[j + 1]); - buf[i++] = temp_byte; - } - len = i; - - final_length = len + IEEE80211_HEADER_SIZE; - final_buf = kmalloc(final_length, GFP_KERNEL); - if (final_buf == NULL) { - SLSI_ERR(sdev, "Malloc failed\n"); - kfree(buf); - return -ENOMEM; - } - - hdr = (struct ieee80211_hdr *)final_buf; - hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, IEEE80211_STYPE_ACTION); - SLSI_ETHER_COPY(hdr->addr1, bssid); - SLSI_ETHER_COPY(hdr->addr2, sdev->hw_addr); - SLSI_ETHER_COPY(hdr->addr3, bssid); - memcpy(final_buf + IEEE80211_HEADER_SIZE, buf, len); - - kfree(buf); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - r = slsi_mlme_send_frame_mgmt(sdev, dev, final_buf, final_length, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, SLSI_FREQ_HOST_TO_FW(freq), dwell_time * 1000, 0); - - kfree(final_buf); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -static ssize_t slsi_setting_max_sta_write(struct net_device *dev, int sta_number) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct slsi_mib_data mib_data = { 0, NULL }; - int result = 0; - - if (sta_number > 10 || sta_number < 1) - return -EINVAL; - result = slsi_mib_encode_uint(&mib_data, SLSI_PSID_UNIFI_MAX_CLIENT, sta_number, 0); - if ((result != SLSI_MIB_STATUS_SUCCESS) || (mib_data.dataLength == 0)) - return -ENOMEM; - result = slsi_mlme_set(sdev, dev, mib_data.data, mib_data.dataLength); - if (result != 0) - SLSI_ERR(sdev, "max_sta: mlme_set_req failed: Result code: %d\n", result); - kfree(mib_data.data); - - return result; -} - -static ssize_t slsi_country_write(struct net_device *dev, char *country_code) -{ - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct slsi_dev *sdev = netdev_vif->sdev; - char alpha2_code[SLSI_COUNTRY_CODE_LEN]; - int status; - - if (strlen(country_code) < 2) - return -EINVAL; - - memcpy(alpha2_code, country_code, 2); - alpha2_code[2] = ' '; /* set 3rd byte of countrycode to ASCII space */ - - status = slsi_set_country_update_regd(sdev, alpha2_code, SLSI_COUNTRY_CODE_LEN); - - return status; -} - -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -static ssize_t slsi_forward_beacon(struct net_device *dev, char *action) -{ - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct slsi_dev *sdev = netdev_vif->sdev; - int intended_action = 0; - int ret = 0; - - if (strncasecmp(action, "stop", 4) == 0) { - intended_action = FAPI_ACTION_STOP; - } else if (strncasecmp(action, "start", 5) == 0) { - intended_action = FAPI_ACTION_START; - } else { - SLSI_NET_ERR(dev, "BEACON_RECV should be used with start or stop\n"); - return -EINVAL; - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "BEACON_RECV %s!!\n", intended_action ? "START" : "STOP"); - SLSI_MUTEX_LOCK(netdev_vif->vif_mutex); - - if ((!netdev_vif->activated) || (netdev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (netdev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_ERR(sdev, "Not a STA vif or status is not CONNECTED\n"); - ret = -EINVAL; - goto exit_vif_mutex; - } - - if (((intended_action == FAPI_ACTION_START) && netdev_vif->is_wips_running) || - ((intended_action == FAPI_ACTION_STOP) && !netdev_vif->is_wips_running)) { - SLSI_NET_INFO(dev, "Forwarding beacon is already %s!!\n", - netdev_vif->is_wips_running ? "running" : "stopped"); - ret = 0; - goto exit_vif_mutex; - } - - SLSI_MUTEX_LOCK(netdev_vif->scan_mutex); - if (intended_action == FAPI_ACTION_START && - (netdev_vif->scan[SLSI_SCAN_HW_ID].scan_req || netdev_vif->sta.roam_in_progress)) { - SLSI_NET_ERR(dev, "Rejecting BEACON_RECV start as scan/roam is running\n"); - ret = -EBUSY; - goto exit_scan_mutex; - } - - ret = slsi_mlme_set_forward_beacon(sdev, dev, intended_action); -exit_scan_mutex: - SLSI_MUTEX_UNLOCK(netdev_vif->scan_mutex); -exit_vif_mutex: - SLSI_MUTEX_UNLOCK(netdev_vif->vif_mutex); - return ret; -} -#endif - -static ssize_t slsi_update_rssi_boost(struct net_device *dev, char *rssi_boost_string) -{ - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct slsi_dev *sdev = netdev_vif->sdev; - int digit1, digit2, band, lendigit1, lendigit2; - int boost = 0, length = 0, i = 0; - - if (strlen(rssi_boost_string) < 8) - return -EINVAL; - for (i = 0; i < (strlen(rssi_boost_string) - 4);) { - if (rssi_boost_string[i] == '0' && - rssi_boost_string[i + 1] == '4') { - if (rssi_boost_string[i + 2] == '0' && - rssi_boost_string[i + 3] == '2' && - ((i + 7) < strlen(rssi_boost_string))) - i = i + 4; - else - return -EINVAL; - digit1 = slsi_parse_hex(rssi_boost_string[i]); - digit2 = slsi_parse_hex(rssi_boost_string[i + 1]); - boost = (digit1 * 16) + digit2; - band = rssi_boost_string[i + 3] - '0'; - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - if (band == 0) { - sdev->device_config.rssi_boost_2g = 0; - sdev->device_config.rssi_boost_5g = 0; - } else if (band == 1) { - sdev->device_config.rssi_boost_2g = 0; - sdev->device_config.rssi_boost_5g = boost; - } else { - sdev->device_config.rssi_boost_2g = boost; - sdev->device_config.rssi_boost_5g = 0; - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - if ((netdev_vif->activated) && - (netdev_vif->vif_type == FAPI_VIFTYPE_STATION)) { - return slsi_set_boost(sdev, dev); - } else { - return 0; - } - } else { - i = i + 2; - lendigit1 = slsi_parse_hex(rssi_boost_string[i]); - lendigit2 = slsi_parse_hex(rssi_boost_string[i + 1]); - length = (lendigit1 * 16) + lendigit2; - i = i + (length * 2) + 2; - } - } - return -EINVAL; -} - -int slsi_set_tx_power_calling(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mode; - int error = 0; - u8 host_state; - - (void)slsi_str_to_int(command, &mode); - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - host_state = sdev->device_config.host_state; - - if (!mode) - host_state = host_state | SLSI_HOSTSTATE_SAR_ACTIVE; - else - host_state = host_state & ~SLSI_HOSTSTATE_SAR_ACTIVE; - - error = slsi_mlme_set_host_state(sdev, dev, host_state); - if (!error) - sdev->device_config.host_state = host_state; - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - return error; -} - -int slsi_set_tx_power_sar(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mode; - int error = 0; - u8 host_state; - - (void)slsi_str_to_int(command, &mode); - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - host_state = sdev->device_config.host_state; - host_state &= ~(SLSI_HOSTSTATE_SAR_ACTIVE | BIT(3) | BIT(4)); - - if (mode) - host_state |= ((mode - 1) << 3) | SLSI_HOSTSTATE_SAR_ACTIVE; - - error = slsi_mlme_set_host_state(sdev, dev, host_state); - if (!error) - sdev->device_config.host_state = host_state; - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - return error; -} - -int slsi_get_tx_power_sar(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int len = 0; - u8 host_state, index; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - host_state = sdev->device_config.host_state; - - if (host_state & SLSI_HOSTSTATE_SAR_ACTIVE) - index = ((host_state >> 3) & 3) + 1; - else - index = 0; - - len = snprintf(command, buf_len, "%u", index); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - return len; -} - -static int slsi_print_regulatory(struct slsi_802_11d_reg_domain *domain_info, char *buf, int buf_len, struct slsi_supported_channels *supported_channels, int supp_chan_length) -{ - int cur_pos = 0; - int i, j, k; - char *dfs_region_str[] = {"unknown", "ETSI", "FCC", "JAPAN", "GLOBAL", "CHINA"}; - u8 dfs_region_index; - struct ieee80211_reg_rule *reg_rule; - int channel_start_freq = 0; - int channel_end_freq = 0; - int channel_start_num = 0; - int channel_end_num = 0; - int channel_count = 0; - int channel_increment = 0; - int channel_band = 0; - bool display_pattern = false; - - cur_pos = snprintf(buf, buf_len, "country %c%c:", domain_info->regdomain->alpha2[0], - domain_info->regdomain->alpha2[1]); - dfs_region_index = domain_info->regdomain->dfs_region <= 5 ? domain_info->regdomain->dfs_region : 0; - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "DFS-%s\n", dfs_region_str[dfs_region_index]); - for (i = 0; i < domain_info->regdomain->n_reg_rules; i++) { - reg_rule = &domain_info->regdomain->reg_rules[i]; - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "\t(%d-%d @ %d), (N/A, %d)", - reg_rule->freq_range.start_freq_khz/1000, - reg_rule->freq_range.end_freq_khz/1000, - reg_rule->freq_range.max_bandwidth_khz/1000, - MBM_TO_DBM(reg_rule->power_rule.max_eirp)); - if (reg_rule->flags) { - if (reg_rule->flags & NL80211_RRF_DFS) - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", DFS"); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (reg_rule->flags & NL80211_RRF_NO_OFDM) - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_OFDM"); -#endif -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) - if (reg_rule->flags & (NL80211_RRF_PASSIVE_SCAN|NL80211_RRF_NO_IBSS)) - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_IR"); -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - if (reg_rule->flags & (NL80211_RRF_NO_IR)) - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_IR"); -#endif - if (reg_rule->flags & NL80211_RRF_NO_INDOOR) - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_INDOOR"); - if (reg_rule->flags & NL80211_RRF_NO_OUTDOOR) - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_OUTDOOR"); - } - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "\n"); - } - - /* Display of Supported Channels for 2.4GHz and 5GHz */ - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "Channels:"); - - for (i = 0; i < supp_chan_length; i++) { - channel_start_num = supported_channels[i].start_chan_num; - channel_count = supported_channels[i].channel_count; - channel_increment = supported_channels[i].increment; - channel_band = supported_channels[i].band; - channel_end_num = channel_start_num + ((channel_count - 1) * channel_increment); - for (j = channel_start_num; j <= channel_end_num; j += channel_increment) { - channel_start_freq = (ieee80211_channel_to_frequency(j, channel_band)*1000) - 10000; - channel_end_freq = (ieee80211_channel_to_frequency(j, channel_band)*1000) + 10000; - for (k = 0; k < domain_info->regdomain->n_reg_rules; k++) { - reg_rule = &domain_info->regdomain->reg_rules[k]; - if ((reg_rule->freq_range.start_freq_khz <= channel_start_freq) && - (reg_rule->freq_range.end_freq_khz >= channel_end_freq)) { - if (display_pattern) - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", %d", j); - else - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, " %d", j); - display_pattern = true; - break; - } - } - } - } - cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "\n"); - return cur_pos; -} - -static int slsi_get_supported_channels(struct slsi_dev *sdev, struct net_device *dev, struct slsi_supported_channels *supported_channels) -{ - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_data supported_chan_mib = { 0, NULL }; - struct slsi_mib_value *values = NULL; - struct slsi_mib_get_entry get_values[] = {{SLSI_PSID_UNIFI_SUPPORTED_CHANNELS, { 0, 0 } } }; - int i, chan_count, chan_start; - int supp_chan_length = 0; - - /* Expect each mib length in response is <= 16. So assume 16 bytes for each MIB */ - mibrsp.dataLength = 16; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (mibrsp.data == NULL) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - return 0; - } - values = slsi_read_mibs(sdev, dev, get_values, 1, &mibrsp); - if (!values) - goto exit_with_mibrsp; - - if (values[0].type != SLSI_MIB_TYPE_OCTET) { - SLSI_ERR(sdev, "Supported_Chan invalid type."); - goto exit_with_values; - } - - supported_chan_mib = values[0].u.octetValue; - for (i = 0; i < supported_chan_mib.dataLength / 2; i++) { - chan_start = supported_chan_mib.data[i*2]; - chan_count = supported_chan_mib.data[i*2 + 1]; - if (chan_start == 1) { /* for 2.4GHz */ - supported_channels[supp_chan_length].start_chan_num = 1; - if (!(sdev->device_config.host_state & SLSI_HOSTSTATE_CELLULAR_ACTIVE) && - chan_count > 11 && sdev->device_config.disable_ch12_ch13) { - chan_count = 11; - SLSI_DBG1(sdev, SLSI_CFG80211, "Channels 12 and 13 have been disabled"); - } - supported_channels[supp_chan_length].channel_count = chan_count; - supported_channels[supp_chan_length].increment = 1; - supported_channels[supp_chan_length].band = NL80211_BAND_2GHZ; - supp_chan_length = supp_chan_length + 1; - } else { /* for 5GHz */ - supported_channels[supp_chan_length].start_chan_num = chan_start; - supported_channels[supp_chan_length].channel_count = chan_count; - supported_channels[supp_chan_length].increment = 4; - supported_channels[supp_chan_length].band = NL80211_BAND_5GHZ; - supp_chan_length = supp_chan_length + 1; - } - } -exit_with_values: - kfree(values); -exit_with_mibrsp: - kfree(mibrsp.data); - return supp_chan_length; -} - -static int slsi_get_regulatory(struct net_device *dev, char *buf, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int mode; - int cur_pos = 0; - int status; - u8 alpha2[3]; - struct slsi_supported_channels supported_channels[5]; - int supp_chan_length; - - mode = buf[strlen(CMD_GETREGULATORY) + 1] - '0'; - if (mode == 1) { - struct slsi_802_11d_reg_domain domain_info; - - memset(&domain_info, 0, sizeof(struct slsi_802_11d_reg_domain)); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated || ndev_vif->vif_type != FAPI_VIFTYPE_STATION || !ndev_vif->sta.sta_bss) { - cur_pos += snprintf(buf, buf_len - cur_pos, "Station not connected"); - SLSI_ERR(sdev, "station not connected. vif.activated:%d, vif.type:%d, vif.bss:%s\n", - ndev_vif->activated, ndev_vif->vif_type, ndev_vif->sta.sta_bss ? "yes" : "no"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - /* read vif specific country code, index = vifid+1 */ - status = slsi_read_default_country(sdev, alpha2, ndev_vif->ifnum + 1); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - if (status) - return status; - - /* max 20 rules */ - domain_info.regdomain = kmalloc(sizeof(*domain_info.regdomain) + sizeof(struct ieee80211_reg_rule) * 20, GFP_KERNEL); - if (!domain_info.regdomain) { - SLSI_ERR(sdev, "no memory size:%lu\n", - sizeof(struct ieee80211_regdomain) + sizeof(struct ieee80211_reg_rule) * 20); - return -ENOMEM; - } - - /* get regulatory rules based on country code */ - domain_info.countrylist = sdev->device_config.domain_info.countrylist; - domain_info.country_len = sdev->device_config.domain_info.country_len; - status = slsi_read_regulatory_rules(sdev, &domain_info, alpha2); - if (status) { - kfree(domain_info.regdomain); - return status; - } - /* get supported channels based on country code */ - supp_chan_length = slsi_get_supported_channels(sdev, dev, &supported_channels[0]); - cur_pos += slsi_print_regulatory(&domain_info, buf + cur_pos, buf_len - cur_pos, &supported_channels[0], supp_chan_length); - kfree(domain_info.regdomain); - } else if (mode == 0) { - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - supp_chan_length = slsi_get_supported_channels(sdev, dev, &supported_channels[0]); - cur_pos += slsi_print_regulatory(&sdev->device_config.domain_info, buf + cur_pos, buf_len - cur_pos, &supported_channels[0], supp_chan_length); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - } else { - cur_pos += snprintf(buf, buf_len - cur_pos, "invalid option %d", mode); - SLSI_ERR(sdev, "invalid option:%d\n", mode); - return -EINVAL; - } - /* Buf is somewhere close to 4Kbytes. so expect some spare space. If there is no spare - * space we might have missed printing some text in buf. - */ - if (buf_len - cur_pos) - return cur_pos; - else - return -ENOMEM; -} - -void slsi_disable_ch12_13(struct slsi_dev *sdev) -{ - struct wiphy *wiphy = sdev->wiphy; - struct ieee80211_channel *chan; - - if (wiphy->bands[0]) { - chan = &wiphy->bands[0]->channels[11]; - chan->flags |= IEEE80211_CHAN_DISABLED; - chan = &wiphy->bands[0]->channels[12]; - chan->flags |= IEEE80211_CHAN_DISABLED; - } - - SLSI_DBG1(sdev, SLSI_CFG80211, "Channels 12 and 13 have been disabled"); -} - -int slsi_set_fcc_channel(struct net_device *dev, char *cmd, int cmd_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int status; - bool flight_mode_ena; - u8 host_state; - int err; - char alpha2[3]; - - /* SET_FCC_CHANNEL 0 when device is in flightmode */ - flight_mode_ena = (cmd[0] == '0'); - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - host_state = sdev->device_config.host_state; - - if (flight_mode_ena) - host_state = host_state & ~SLSI_HOSTSTATE_CELLULAR_ACTIVE; - else - host_state = host_state | SLSI_HOSTSTATE_CELLULAR_ACTIVE; - sdev->device_config.host_state = host_state; - - status = slsi_mlme_set_host_state(sdev, dev, host_state); - if (status) { - SLSI_ERR(sdev, "Err setting MMaxPowerEna. error = %d\n", status); - } else { - err = slsi_read_default_country(sdev, alpha2, 1); - if (err) { - SLSI_WARN(sdev, "Err updating reg_rules = %d\n", err); - } else { - memcpy(sdev->device_config.domain_info.regdomain->alpha2, alpha2, 2); - /* Read the regulatory params for the country.*/ - if (slsi_read_regulatory_rules(sdev, &sdev->device_config.domain_info, alpha2) == 0) { - slsi_reset_channel_flags(sdev); - wiphy_apply_custom_regulatory(sdev->wiphy, sdev->device_config.domain_info.regdomain); - slsi_update_supported_channels_regd_flags(sdev); - if (flight_mode_ena && sdev->device_config.disable_ch12_ch13) - slsi_disable_ch12_13(sdev); - } - } - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - return status; -} - -int slsi_fake_mac_write(struct net_device *dev, char *cmd) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct slsi_mib_data mib_data = { 0, NULL }; - int status; - bool enable; - - if (strncmp(cmd, "ON", strlen("ON")) == 0) - enable = 1; - else - enable = 0; - - status = slsi_mib_encode_bool(&mib_data, SLSI_PSID_UNIFI_MAC_ADDRESS_RANDOMISATION, enable, 0); - if (status != SLSI_MIB_STATUS_SUCCESS) { - SLSI_ERR(sdev, "FAKE MAC FAIL: no mem for MIB\n"); - return -ENOMEM; - } - - status = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - - kfree(mib_data.data); - - if (status) - SLSI_ERR(sdev, "Err setting unifiMacAddrRandomistaion MIB. error = %d\n", status); - - return status; -} - -static char *slsi_get_assoc_status(u16 fw_result_code) -{ - char *assoc_status_label = "unspecified_failure"; - - switch (fw_result_code) { - case FAPI_RESULTCODE_SUCCESS: - assoc_status_label = "success"; - break; - case FAPI_RESULTCODE_TRANSMISSION_FAILURE: - assoc_status_label = "transmission_failure"; - break; - case FAPI_RESULTCODE_HOST_REQUEST_SUCCESS: - assoc_status_label = "host_request_success"; - break; - case FAPI_RESULTCODE_HOST_REQUEST_FAILED: - assoc_status_label = "host_request_failed"; - break; - case FAPI_RESULTCODE_PROBE_TIMEOUT: - assoc_status_label = "probe_timeout"; - break; - case FAPI_RESULTCODE_AUTH_TIMEOUT: - assoc_status_label = "auth_timeout"; - break; - case FAPI_RESULTCODE_ASSOC_TIMEOUT: - assoc_status_label = "assoc_timeout"; - break; - case FAPI_RESULTCODE_ASSOC_ABORT: - assoc_status_label = "assoc_abort"; - break; - } - return assoc_status_label; -} - -int slsi_get_sta_info(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int len; -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - struct net_device *ap_dev; - struct netdev_vif *ndev_ap_vif; - - ap_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN); - - if (ap_dev) { - ndev_ap_vif = netdev_priv(ap_dev); - SLSI_MUTEX_LOCK(ndev_ap_vif->vif_mutex); - if (SLSI_IS_VIF_INDEX_MHS(sdev, ndev_ap_vif)) - ndev_vif = ndev_ap_vif; - SLSI_MUTEX_UNLOCK(ndev_ap_vif->vif_mutex); - } -#endif - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_AP)) { - SLSI_ERR(sdev, "slsi_get_sta_info: AP is not up.Command not allowed vif.activated:%d, vif.type:%d\n", - ndev_vif->activated, ndev_vif->vif_type); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - -#if defined(ANDROID_VERSION) && (ANDROID_VERSION >= 90000) - len = snprintf(command, buf_len, "GETSTAINFO %pM Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d CAP=%04x %02x:%02x:%02x ", - ndev_vif->ap.last_disconnected_sta.address, - ndev_vif->ap.last_disconnected_sta.rx_retry_packets, - ndev_vif->ap.last_disconnected_sta.rx_bc_mc_packets, - ndev_vif->ap.last_disconnected_sta.capabilities, - ndev_vif->ap.last_disconnected_sta.address[0], - ndev_vif->ap.last_disconnected_sta.address[1], - ndev_vif->ap.last_disconnected_sta.address[2]); - - len += snprintf(&command[len], (buf_len - len), "%d %d %d %d %d %d %d %u %d", - ieee80211_frequency_to_channel(ndev_vif->ap.channel_freq), - ndev_vif->ap.last_disconnected_sta.bandwidth, ndev_vif->ap.last_disconnected_sta.rssi, - ndev_vif->ap.last_disconnected_sta.tx_data_rate, ndev_vif->ap.last_disconnected_sta.mode, - ndev_vif->ap.last_disconnected_sta.antenna_mode, - ndev_vif->ap.last_disconnected_sta.mimo_used, ndev_vif->ap.last_disconnected_sta.reason, - ndev_vif->ap.last_disconnected_sta.support_mode); -#else - len = snprintf(command, buf_len, "wl_get_sta_info : %02x%02x%02x %u %d %d %d %d %d %d %u ", - ndev_vif->ap.last_disconnected_sta.address[0], ndev_vif->ap.last_disconnected_sta.address[1], - ndev_vif->ap.last_disconnected_sta.address[2], ndev_vif->ap.channel_freq, - ndev_vif->ap.last_disconnected_sta.bandwidth, ndev_vif->ap.last_disconnected_sta.rssi, - ndev_vif->ap.last_disconnected_sta.tx_data_rate, ndev_vif->ap.last_disconnected_sta.mode, - ndev_vif->ap.last_disconnected_sta.antenna_mode, - ndev_vif->ap.last_disconnected_sta.mimo_used, ndev_vif->ap.last_disconnected_sta.reason); -#endif - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return len; -} - -static int slsi_get_bss_rssi(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int len = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - len = snprintf(command, buf_len, "%d", ndev_vif->sta.last_connected_bss.rssi); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return len; -} - -static int slsi_get_bss_info(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int len = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - len = snprintf(command, buf_len, "%02x:%02x:%02x %u %u %d %u %u %u %u %u %d %d %u %u %u %u", - ndev_vif->sta.last_connected_bss.address[0], ndev_vif->sta.last_connected_bss.address[1], - ndev_vif->sta.last_connected_bss.address[2], - ndev_vif->sta.last_connected_bss.channel_freq, ndev_vif->sta.last_connected_bss.bandwidth, - ndev_vif->sta.last_connected_bss.rssi, ndev_vif->sta.last_connected_bss.tx_data_rate, - ndev_vif->sta.last_connected_bss.mode, ndev_vif->sta.last_connected_bss.antenna_mode, - ndev_vif->sta.last_connected_bss.mimo_used, - ndev_vif->sta.last_connected_bss.passpoint_version, ndev_vif->sta.last_connected_bss.snr, - ndev_vif->sta.last_connected_bss.noise_level, ndev_vif->sta.last_connected_bss.roaming_akm, - ndev_vif->sta.last_connected_bss.roaming_count, ndev_vif->sta.last_connected_bss.kv, - ndev_vif->sta.last_connected_bss.kvie); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return len; -} - -static int slsi_get_linkspeed(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int len = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - SLSI_ERR(sdev, "Not Activated, Command not allowed vif.activated:%d, vif.type:%d\n", - ndev_vif->activated, ndev_vif->vif_type); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - - if ((ndev_vif->vif_type != FAPI_VIFTYPE_STATION) && (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_NET_ERR(dev, "sta is not in connected state\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EPERM; - } - - len = snprintf(command, buf_len, "MAX_SPEED %u CURRENT_LINK_SPEED %u", - ndev_vif->sta.max_rate_mbps, ndev_vif->sta.data_rate_mbps); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return len; -} - -static int slsi_get_assoc_reject_info(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int len = 0; - - len = snprintf(command, buf_len, "assoc_reject.status : %d %s", sdev->assoc_result_code, - slsi_get_assoc_status(sdev->assoc_result_code)); - - return len; -} - -#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE -static int slsi_set_power_mode(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int status; - u16 power_mode; - - power_mode = (command[0] == '0') ? FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE : FAPI_POWERMANAGEMENTMODE_POWER_SAVE; - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - !(ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - SLSI_ERR(sdev, "Command not allowed vif.activated:%d, vif.type:%d, ndev_vif->sta.vif_status:%d\n", - ndev_vif->activated, ndev_vif->vif_type, ndev_vif->sta.vif_status); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - status = slsi_mlme_powermgt(sdev, dev, power_mode); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return status; -} -#endif - -int slsi_set_disconnect_ies(struct net_device *dev, char *cmd, int cmd_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - char *disconnect_ies = cmd + strlen(CMD_SET_DISCONNECT_IES) + 1; - int ie_len = 0; - u8 *disconnect_ies_bin; - u8 temp_byte; - int i; - int j; - int len; - - SLSI_DBG1(sdev, SLSI_CFG80211, "Setting disconnect IE's\n"); - while (disconnect_ies[ie_len]) - ie_len++; - - /* ie_len has been trimmed to even, as odd length would mean that ie is invalid */ - ie_len &= (~0x01); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - ndev_vif->sta.vendor_disconnect_ies_len = (ie_len / 2); - disconnect_ies_bin = kmalloc(ndev_vif->sta.vendor_disconnect_ies_len, GFP_KERNEL); - if (!disconnect_ies_bin) { - SLSI_ERR(sdev, "Malloc failed\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -ENOMEM; - } - - for (i = 0, j = 0; j < ie_len; j += 2) { - temp_byte = slsi_parse_hex(disconnect_ies[j]) << 4 | slsi_parse_hex(disconnect_ies[j + 1]); - disconnect_ies_bin[i++] = temp_byte; - } - - /* check if the IE is valid */ - for (i = 0; i < ndev_vif->sta.vendor_disconnect_ies_len;) { - if (disconnect_ies_bin[i] == 0xdd) { - len = disconnect_ies_bin[i + 1]; - if ((ndev_vif->sta.vendor_disconnect_ies_len - (i + 2)) < len) { - SLSI_WARN(sdev, "The length of disconnect IE's is not proper\n"); - ndev_vif->sta.vendor_disconnect_ies_len = 0; - kfree(disconnect_ies_bin); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - - i = i + 2 + len; - } else { - SLSI_WARN(sdev, "The tag of disconnect IE's is not proper\n"); - ndev_vif->sta.vendor_disconnect_ies_len = 0; - kfree(disconnect_ies_bin); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EINVAL; - } - } - ndev_vif->sta.vendor_disconnect_ies = disconnect_ies_bin; - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return 0; -} - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -static int slsi_enhanced_arp_start_stop(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int result = 0; - int readbyte = 0; - int readvalue = 0; - int i = 0; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - if (!sdev->device_config.fw_enhanced_arp_detect_supported) { - SLSI_ERR(sdev, "Enhanced ARP Detect Feature is not supported.\n"); - return -ENOTSUPP; - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) { - SLSI_ERR(sdev, "Not in STA mode\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex) - return -EPERM; - } - - SLSI_DBG1(sdev, SLSI_CFG80211, "Enhanced ARP Start/Stop\n"); - - for (i = 0; i < 4 ; i++) { - readbyte = slsi_str_to_int(command, &readvalue); - ndev_vif->target_ip_addr[i] = readvalue; - command = command + readbyte + 1; - } - - if (ndev_vif->target_ip_addr[0] != 0) { /* start enhanced arp detect */ - /* clear all the counters */ - memset(&ndev_vif->enhanced_arp_stats, 0, sizeof(ndev_vif->enhanced_arp_stats)); - ndev_vif->enhanced_arp_detect_enabled = true; - result = slsi_mlme_arp_detect_request(sdev, dev, FAPI_ACTION_START, ndev_vif->target_ip_addr); - } else { /* stop enhanced arp detect */ - ndev_vif->enhanced_arp_detect_enabled = false; - result = slsi_mlme_arp_detect_request(sdev, dev, FAPI_ACTION_STOP, ndev_vif->target_ip_addr); - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return result; -} - -static int slsi_enhanced_arp_get_stats(struct net_device *dev, char *command, int buf_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int r = 0; - int len = 0; - - r = slsi_read_enhanced_arp_rx_count_by_lower_mac(sdev, dev, SLSI_PSID_UNIFI_ARP_DETECT_RESPONSE_COUNTER); - - if (r == 0) { - len = snprintf(command, buf_len, "%d %d %d %d %d %d %d %d %d %d", - ndev_vif->enhanced_arp_stats.arp_req_count_from_netdev, - ndev_vif->enhanced_arp_stats.arp_req_count_to_lower_mac, - ndev_vif->enhanced_arp_stats.arp_req_rx_count_by_lower_mac, - ndev_vif->enhanced_arp_stats.arp_req_count_tx_success, - ndev_vif->enhanced_arp_stats.arp_rsp_rx_count_by_lower_mac, - ndev_vif->enhanced_arp_stats.arp_rsp_rx_count_by_upper_mac, - ndev_vif->enhanced_arp_stats.arp_rsp_count_to_netdev, - ndev_vif->enhanced_arp_stats.arp_rsp_count_out_of_order_drop, - 0, /*ap_link_active not supported, set as 0*/ - ndev_vif->enhanced_arp_stats.is_duplicate_addr_detected); - } - - /*clear all the counters*/ - memset(&ndev_vif->enhanced_arp_stats, 0, sizeof(ndev_vif->enhanced_arp_stats)); - - return len; -} -#endif - -int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ -#define MAX_LEN_PRIV_COMMAND 4096 /*This value is the max reply size set in supplicant*/ - struct android_wifi_priv_cmd priv_cmd; - int ret = 0; - u8 *command = NULL; - - if (!dev) { - ret = -ENODEV; - goto exit; - } - - if (!rq->ifr_data) { - ret = -EINVAL; - goto exit; - } - if (copy_from_user((void *)&priv_cmd, (void *)rq->ifr_data, sizeof(struct android_wifi_priv_cmd))) { - ret = -EFAULT; - SLSI_NET_ERR(dev, "ifr data failed\n"); - goto exit; - } - - if ((priv_cmd.total_len > MAX_LEN_PRIV_COMMAND) || (priv_cmd.total_len < 0)) { - ret = -EINVAL; - SLSI_NET_ERR(dev, "Length mismatch total_len = %d\n", priv_cmd.total_len); - goto exit; - } - command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL); - if (!command) { - ret = -ENOMEM; - SLSI_NET_ERR(dev, "No memory\n"); - goto exit; - } - if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { - ret = -EFAULT; - SLSI_NET_ERR(dev, "Buffer copy fail\n"); - goto exit; - } - command[priv_cmd.total_len] = '\0'; - - SLSI_INFO_NODEV("command: %.*s\n", priv_cmd.total_len, command); - - if (strncasecmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { - ret = slsi_set_suspend_mode(dev, command); - } else if (strncasecmp(command, CMD_SETJOINPREFER, strlen(CMD_SETJOINPREFER)) == 0) { - char *rssi_boost_string = command + strlen(CMD_SETJOINPREFER) + 1; - - ret = slsi_update_rssi_boost(dev, rssi_boost_string); - } else if (strncasecmp(command, CMD_RXFILTERADD, strlen(CMD_RXFILTERADD)) == 0) { - int filter_num = *(command + strlen(CMD_RXFILTERADD) + 1) - '0'; - - ret = slsi_rx_filter_num_write(dev, 1, filter_num); - } else if (strncasecmp(command, CMD_RXFILTERREMOVE, strlen(CMD_RXFILTERREMOVE)) == 0) { - int filter_num = *(command + strlen(CMD_RXFILTERREMOVE) + 1) - '0'; - - ret = slsi_rx_filter_num_write(dev, 0, filter_num); -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if !defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION < 90000) - } else if (strncasecmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) { - char *intf_name = command + strlen(CMD_INTERFACE_CREATE) + 1; - - ret = slsi_create_interface(dev, intf_name); - } else if (strncasecmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) { - char *intf_name = command + strlen(CMD_INTERFACE_DELETE) + 1; - - ret = slsi_delete_interface(dev, intf_name); -#endif - } else if (strncasecmp(command, CMD_SET_INDOOR_CHANNELS, strlen(CMD_SET_INDOOR_CHANNELS)) == 0) { - char *arg = command + strlen(CMD_SET_INDOOR_CHANNELS) + 1; - - ret = slsi_set_indoor_channels(dev, arg); - } else if (strncasecmp(command, CMD_GET_INDOOR_CHANNELS, strlen(CMD_GET_INDOOR_CHANNELS)) == 0) { - ret = slsi_get_indoor_channels(dev, command, priv_cmd.total_len); -#endif - } else if (strncasecmp(command, CMD_SETCOUNTRYREV, strlen(CMD_SETCOUNTRYREV)) == 0) { - char *country_code = command + strlen(CMD_SETCOUNTRYREV) + 1; - - ret = slsi_set_country_rev(dev, country_code); - } else if (strncasecmp(command, CMD_GETCOUNTRYREV, strlen(CMD_GETCOUNTRYREV)) == 0) { - ret = slsi_get_country_rev(dev, command, priv_cmd.total_len); -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - } else if (strncasecmp(command, CMD_SETROAMTRIGGER, strlen(CMD_SETROAMTRIGGER)) == 0) { - int skip = strlen(CMD_SETROAMTRIGGER) + 1; - - ret = slsi_roam_scan_trigger_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETROAMTRIGGER, strlen(CMD_GETROAMTRIGGER)) == 0) { - ret = slsi_roam_scan_trigger_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETROAMDELTA, strlen(CMD_SETROAMDELTA)) == 0) { - int skip = strlen(CMD_SETROAMDELTA) + 1; - - ret = slsi_roam_delta_trigger_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETROAMDELTA, strlen(CMD_GETROAMDELTA)) == 0) { - ret = slsi_roam_delta_trigger_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETROAMSCANPERIOD, strlen(CMD_SETROAMSCANPERIOD)) == 0) { - int skip = strlen(CMD_SETROAMSCANPERIOD) + 1; - - ret = slsi_cached_channel_scan_period_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETROAMSCANPERIOD, strlen(CMD_GETROAMSCANPERIOD)) == 0) { - ret = slsi_cached_channel_scan_period_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETFULLROAMSCANPERIOD, strlen(CMD_SETFULLROAMSCANPERIOD)) == 0) { - int skip = strlen(CMD_SETFULLROAMSCANPERIOD) + 1; - - ret = slsi_full_roam_scan_period_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETFULLROAMSCANPERIOD, strlen(CMD_GETFULLROAMSCANPERIOD)) == 0) { - ret = slsi_full_roam_scan_period_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETSCANCHANNELTIME, strlen(CMD_SETSCANCHANNELTIME)) == 0) { - int skip = strlen(CMD_SETSCANCHANNELTIME) + 1; - - ret = slsi_roam_scan_max_active_channel_time_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETSCANCHANNELTIME, strlen(CMD_GETSCANCHANNELTIME)) == 0) { - ret = slsi_roam_scan_max_active_channel_time_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETSCANNPROBES, strlen(CMD_SETSCANNPROBES)) == 0) { - int skip = strlen(CMD_SETSCANNPROBES) + 1; - - ret = slsi_roam_scan_probe_interval_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETSCANNPROBES, strlen(CMD_GETSCANNPROBES)) == 0) { - ret = slsi_roam_scan_probe_interval_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0) { - int skip = strlen(CMD_SETROAMMODE) + 1; - - ret = slsi_roam_mode_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETROAMMODE, strlen(CMD_GETROAMMODE)) == 0) { - ret = slsi_roam_mode_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETROAMINTRABAND, strlen(CMD_SETROAMINTRABAND)) == 0) { - int skip = strlen(CMD_SETROAMINTRABAND) + 1; - - ret = slsi_roam_scan_band_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETROAMINTRABAND, strlen(CMD_GETROAMINTRABAND)) == 0) { - ret = slsi_roam_scan_band_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETROAMBAND, strlen(CMD_SETROAMBAND)) == 0) { - uint band = *(command + strlen(CMD_SETROAMBAND) + 1) - '0'; - - ret = slsi_freq_band_write(dev, band); - } else if (strncasecmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { - uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; - - ret = slsi_freq_band_write(dev, band); - } else if ((strncasecmp(command, CMD_GETROAMBAND, strlen(CMD_GETROAMBAND)) == 0) || (strncasecmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0)) { - ret = slsi_freq_band_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETROAMSCANCONTROL, strlen(CMD_SETROAMSCANCONTROL)) == 0) { - int mode = *(command + strlen(CMD_SETROAMSCANCONTROL) + 1) - '0'; - - ret = slsi_roam_scan_control_write(dev, mode); - } else if (strncasecmp(command, CMD_GETROAMSCANCONTROL, strlen(CMD_GETROAMSCANCONTROL)) == 0) { - ret = slsi_roam_scan_control_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETSCANHOMETIME, strlen(CMD_SETSCANHOMETIME)) == 0) { - int skip = strlen(CMD_SETSCANHOMETIME) + 1; - - ret = slsi_roam_scan_home_time_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETSCANHOMETIME, strlen(CMD_GETSCANHOMETIME)) == 0) { - ret = slsi_roam_scan_home_time_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETSCANHOMEAWAYTIME, strlen(CMD_SETSCANHOMEAWAYTIME)) == 0) { - int skip = strlen(CMD_SETSCANHOMEAWAYTIME) + 1; - - ret = slsi_roam_scan_home_away_time_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETSCANHOMEAWAYTIME, strlen(CMD_GETSCANHOMEAWAYTIME)) == 0) { - ret = slsi_roam_scan_home_away_time_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETOKCMODE, strlen(CMD_SETOKCMODE)) == 0) { - int mode = *(command + strlen(CMD_SETOKCMODE) + 1) - '0'; - - ret = slsi_okc_mode_write(dev, mode); - } else if (strncasecmp(command, CMD_GETOKCMODE, strlen(CMD_GETOKCMODE)) == 0) { - ret = slsi_okc_mode_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETWESMODE, strlen(CMD_SETWESMODE)) == 0) { - int mode = *(command + strlen(CMD_SETWESMODE) + 1) - '0'; - - ret = slsi_wes_mode_write(dev, mode); - } else if (strncasecmp(command, CMD_GETWESMODE, strlen(CMD_GETWESMODE)) == 0) { - ret = slsi_wes_mode_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SETROAMSCANCHANNELS, strlen(CMD_SETROAMSCANCHANNELS)) == 0) { - int skip = strlen(CMD_SETROAMSCANCHANNELS) + 1; - - ret = slsi_roam_scan_channels_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GETROAMSCANCHANNELS, strlen(CMD_GETROAMSCANCHANNELS)) == 0) { - ret = slsi_roam_scan_channels_read(dev, command, priv_cmd.total_len); -#endif - } else if (strncasecmp(command, CMD_SET_PMK, strlen(CMD_SET_PMK)) == 0) { - ret = slsi_set_pmk(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_HAPD_GET_CHANNEL, strlen(CMD_HAPD_GET_CHANNEL)) == 0) { - ret = slsi_auto_chan_read(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_SET_SAP_CHANNEL_LIST, strlen(CMD_SET_SAP_CHANNEL_LIST)) == 0) { - int skip = strlen(CMD_SET_SAP_CHANNEL_LIST) + 1; - - ret = slsi_auto_chan_write(dev, command + skip); - } else if (strncasecmp(command, CMD_REASSOC, strlen(CMD_REASSOC)) == 0) { - int skip = strlen(CMD_REASSOC) + 1; - - ret = slsi_reassoc_write(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_SENDACTIONFRAME, strlen(CMD_SENDACTIONFRAME)) == 0) { - int skip = strlen(CMD_SENDACTIONFRAME) + 1; - - ret = slsi_send_action_frame(dev, command + skip, - priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_HAPD_MAX_NUM_STA, strlen(CMD_HAPD_MAX_NUM_STA)) == 0) { - int sta_num; - u8 *max_sta = command + strlen(CMD_HAPD_MAX_NUM_STA) + 1; - - slsi_str_to_int(max_sta, &sta_num); - ret = slsi_setting_max_sta_write(dev, sta_num); - } else if (strncasecmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { - char *country_code = command + strlen(CMD_COUNTRY) + 1; - - ret = slsi_country_write(dev, country_code); -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - } else if (strncasecmp(command, CMD_BEACON_RECV, strlen(CMD_BEACON_RECV)) == 0) { - char *action = command + strlen(CMD_BEACON_RECV) + 1; - - ret = slsi_forward_beacon(dev, action); -#endif - } else if (strncasecmp(command, CMD_SETAPP2PWPSIE, strlen(CMD_SETAPP2PWPSIE)) == 0) { - ret = slsi_set_ap_p2p_wps_ie(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_P2PSETPS, strlen(CMD_P2PSETPS)) == 0) { - ret = slsi_set_p2p_oppps(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_P2PSETNOA, strlen(CMD_P2PSETNOA)) == 0) { - ret = slsi_p2p_set_noa_params(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_P2PECSA, strlen(CMD_P2PECSA)) == 0) { - ret = slsi_p2p_ecsa(dev, command); - } else if (strncasecmp(command, CMD_P2PLOSTART, strlen(CMD_P2PLOSTART)) == 0) { - ret = slsi_p2p_lo_start(dev, command); - } else if (strncasecmp(command, CMD_P2PLOSTOP, strlen(CMD_P2PLOSTOP)) == 0) { - ret = slsi_p2p_lo_stop(dev); - } else if (strncasecmp(command, CMD_SETROAMOFFLOAD, strlen(CMD_SETROAMOFFLOAD)) == 0) { - ret = slsi_roam_mode_write(dev, command + strlen(CMD_SETROAMOFFLOAD) + 1, - priv_cmd.total_len - (strlen(CMD_SETROAMOFFLOAD) + 1)); - } else if (strncasecmp(command, CMD_SETROAMOFFLAPLIST, strlen(CMD_SETROAMOFFLAPLIST)) == 0) { - ret = slsi_roam_offload_ap_list(dev, command + strlen(CMD_SETROAMOFFLAPLIST) + 1, - priv_cmd.total_len - (strlen(CMD_SETROAMOFFLAPLIST) + 1)); - } else if (strncasecmp(command, CMD_SET_TX_POWER_CALLING, strlen(CMD_SET_TX_POWER_CALLING)) == 0) { - ret = slsi_set_tx_power_calling(dev, command + strlen(CMD_SET_TX_POWER_CALLING) + 1, - priv_cmd.total_len - (strlen(CMD_SET_TX_POWER_CALLING) + 1)); - } else if (strncasecmp(command, CMD_SET_TX_POWER_SAR, strlen(CMD_SET_TX_POWER_SAR)) == 0) { - ret = slsi_set_tx_power_sar(dev, command + strlen(CMD_SET_TX_POWER_SAR) + 1, - priv_cmd.total_len - (strlen(CMD_SET_TX_POWER_SAR) + 1)); - } else if (strncasecmp(command, CMD_GET_TX_POWER_SAR, strlen(CMD_GET_TX_POWER_SAR)) == 0) { - ret = slsi_get_tx_power_sar(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_GETREGULATORY, strlen(CMD_GETREGULATORY)) == 0) { - ret = slsi_get_regulatory(dev, command, priv_cmd.total_len); -#ifdef CONFIG_SCSC_WLAN_HANG_TEST - } else if (strncasecmp(command, CMD_TESTFORCEHANG, strlen(CMD_TESTFORCEHANG)) == 0) { - ret = slsi_test_send_hanged_vendor_event(dev); -#endif - } else if (strncasecmp(command, CMD_SET_FCC_CHANNEL, strlen(CMD_SET_FCC_CHANNEL)) == 0) { - ret = slsi_set_fcc_channel(dev, command + strlen(CMD_SET_FCC_CHANNEL) + 1, - priv_cmd.total_len - (strlen(CMD_SET_FCC_CHANNEL) + 1)); - } else if (strncasecmp(command, CMD_FAKEMAC, strlen(CMD_FAKEMAC)) == 0) { - ret = slsi_fake_mac_write(dev, command + strlen(CMD_FAKEMAC) + 1); - } else if (strncasecmp(command, CMD_GETBSSRSSI, strlen(CMD_GETBSSRSSI)) == 0) { - ret = slsi_get_bss_rssi(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_GETBSSINFO, strlen(CMD_GETBSSINFO)) == 0) { - ret = slsi_get_bss_info(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_GETSTAINFO, strlen(CMD_GETSTAINFO)) == 0) { - ret = slsi_get_sta_info(dev, command, priv_cmd.total_len); - } else if (strncasecmp(command, CMD_GETASSOCREJECTINFO, strlen(CMD_GETASSOCREJECTINFO)) == 0) { - ret = slsi_get_assoc_reject_info(dev, command, priv_cmd.total_len); -#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE - } else if (strncasecmp(command, CMD_SET_LATENCY_MODE, strlen(CMD_SET_LATENCY_MODE)) == 0) { - int latency_mode = *(command + strlen(CMD_SET_LATENCY_MODE) + 1) - '0'; - int cmd_len = priv_cmd.total_len - (strlen(CMD_SET_LATENCY_MODE) + 1); - - ret = slsi_set_latency_mode(dev, latency_mode, cmd_len); - } else if (strncasecmp(command, CMD_SET_POWER_MGMT, strlen(CMD_SET_POWER_MGMT)) == 0) { - ret = slsi_set_power_mode(dev, command + strlen(CMD_SET_POWER_MGMT) + 1, - priv_cmd.total_len - (strlen(CMD_SET_POWER_MGMT) + 1)); -#endif - } else if (strncasecmp(command, CMD_SET_DISCONNECT_IES, strlen(CMD_SET_DISCONNECT_IES)) == 0) { - ret = slsi_set_disconnect_ies(dev, command, priv_cmd.total_len); -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - } else if (strncasecmp(command, CMD_SET_ENHANCED_ARP_TARGET, strlen(CMD_SET_ENHANCED_ARP_TARGET)) == 0) { - int skip = strlen(CMD_SET_ENHANCED_ARP_TARGET) + 1; - - ret = slsi_enhanced_arp_start_stop(dev, command + skip, priv_cmd.total_len - skip); - } else if (strncasecmp(command, CMD_GET_ENHANCED_ARP_COUNTS, strlen(CMD_SET_ENHANCED_ARP_TARGET)) == 0) { - ret = slsi_enhanced_arp_get_stats(dev, command, priv_cmd.total_len); -#endif - } else if ((strncasecmp(command, CMD_RXFILTERSTART, strlen(CMD_RXFILTERSTART)) == 0) || - (strncasecmp(command, CMD_RXFILTERSTOP, strlen(CMD_RXFILTERSTOP)) == 0) || - (strncasecmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) || - (strncasecmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) || - (strncasecmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) || - (strncasecmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)) { - ret = 0; - } else if ((strncasecmp(command, CMD_AMPDU_MPDU, strlen(CMD_AMPDU_MPDU)) == 0) || - (strncasecmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0) || - (strncasecmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) || - (strncasecmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) || - (strncasecmp(command, CMD_LTECOEX, strlen(CMD_LTECOEX)) == 0) || - (strncasecmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0) || - (strncasecmp(command, CMD_RPSMODE, strlen(CMD_RPSMODE)) == 0) || - (strncasecmp(command, CMD_SETCCXMODE, strlen(CMD_SETCCXMODE)) == 0) || - (strncasecmp(command, CMD_SETDFSSCANMODE, strlen(CMD_SETDFSSCANMODE)) == 0) || - (strncasecmp(command, CMD_SETSINGLEANT, strlen(CMD_SETSINGLEANT)) == 0)) { - ret = -ENOTSUPP; -#ifndef SLSI_TEST_DEV - } else if ((strncasecmp(command, CMD_DRIVERDEBUGDUMP, strlen(CMD_DRIVERDEBUGDUMP)) == 0) || - (strncasecmp(command, CMD_DRIVERDEBUGCOMMAND, strlen(CMD_DRIVERDEBUGCOMMAND)) == 0)) { - slsi_dump_stats(dev); -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_schedule_collection(SCSC_LOG_DUMPSTATE, SCSC_LOG_DUMPSTATE_REASON_DRIVERDEBUGDUMP); -#else - ret = mx140_log_dump(); -#endif -#endif -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - } else if ((strncasecmp(command, CMD_ENHANCED_PKT_FILTER, strlen(CMD_ENHANCED_PKT_FILTER)) == 0)) { - const u8 enable = *(command + strlen(CMD_ENHANCED_PKT_FILTER) + 1) - '0'; - - ret = slsi_set_enhanced_pkt_filter(dev, enable); -#endif -#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER - } else if ((strncasecmp(command, CMD_ABNORMAL_MULTICAST_PKT_FILTER, strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER)) == 0)) { - const u8 enable = *(command + strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER) + 1) - '0'; - - ret = slsi_set_abnormal_multicast_pkt_filter(dev, enable); -#endif -#ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS - } else if (strncasecmp(command, CMD_SET_NUM_ANTENNAS, strlen(CMD_SET_NUM_ANTENNAS)) == 0) { - struct netdev_vif *ndev_vif = netdev_priv(dev); - const u16 num_of_antennas = *(command + strlen(CMD_SET_NUM_ANTENNAS) + 1) - '0'; - - /* We cannot lock in slsi_set_num_antennas as - * this is also called in slsi_start_ap with netdev_vif lock. - */ - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - ret = slsi_set_num_antennas(dev, num_of_antennas); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -#endif - } else if ((strncasecmp(command, CMD_GET_MAX_LINK_SPEED, strlen(CMD_GET_MAX_LINK_SPEED)) == 0)) { - ret = slsi_get_linkspeed(dev, command, priv_cmd.total_len); - } else { - ret = -ENOTSUPP; - } - if (strncasecmp(command, CMD_SETROAMBAND, strlen(CMD_SETROAMBAND)) != 0 && strncasecmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) != 0 && copy_to_user(priv_cmd.buf, command, priv_cmd.total_len)) { - ret = -EFAULT; - SLSI_NET_ERR(dev, "Buffer copy fail\n"); - } - -exit: - kfree(command); - return ret; -} diff --git a/drivers/net/wireless/scsc/ioctl.h b/drivers/net/wireless/scsc/ioctl.h deleted file mode 100755 index 245c8f3b81cf..000000000000 --- a/drivers/net/wireless/scsc/ioctl.h +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef __MX_IOCTL_H__ -#define __MX_IOCTL_H__ - -#include -#include - -struct android_wifi_priv_cmd { - char *buf; - int used_len; - int total_len; -}; - -int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -int slsi_get_sta_info(struct net_device *dev, char *command, int buf_len); - -struct slsi_supported_channels { - int start_chan_num; - int channel_count; - int increment; - int band; -}; -#endif /* __MX_IOCTL_H__ */ diff --git a/drivers/net/wireless/scsc/kic.c b/drivers/net/wireless/scsc/kic.c deleted file mode 100755 index a139a93e7b05..000000000000 --- a/drivers/net/wireless/scsc/kic.c +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include -#include "dev.h" -#include "debug.h" -#include "mxman.h" - -static int wifi_kic_trigger_recovery(void *priv, enum slsi_kic_test_recovery_type type) -{ - struct slsi_dev *sdev = (struct slsi_dev *)priv; - char reason[80]; - - if (!sdev) - return -EINVAL; - - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) - return -EAGAIN; - - switch (type) { - case slsi_kic_test_recovery_type_subsystem_panic: - SLSI_INFO(sdev, "Trigger Wi-Fi firmware subsystem panic\n"); - if (scsc_service_force_panic(sdev->service)) - return -EINVAL; - return 0; - case slsi_kic_test_recovery_type_emulate_firmware_no_response: - SLSI_INFO(sdev, "Trigger Wi-Fi host panic\n"); - snprintf(reason, sizeof(reason), "slsi_kic_test_recovery_type_emulate_firmware_no_response"); - slsi_sm_service_failed(sdev, reason); - return 0; - case slsi_kic_test_recovery_type_watch_dog: - case slsi_kic_test_recovery_type_chip_crash: - default: - return -EINVAL; - } -} - -static struct slsi_kic_wifi_ops kic_ops = { - .trigger_recovery = wifi_kic_trigger_recovery, -}; - -int wifi_kic_register(struct slsi_dev *sdev) -{ - return slsi_kic_wifi_ops_register((void *)sdev, &kic_ops); -} - -void wifi_kic_unregister(void) -{ - return slsi_kic_wifi_ops_unregister(&kic_ops); -} diff --git a/drivers/net/wireless/scsc/kic.h b/drivers/net/wireless/scsc/kic.h deleted file mode 100644 index ca714a2aa203..000000000000 --- a/drivers/net/wireless/scsc/kic.h +++ /dev/null @@ -1,13 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __KIC_H -#define __KIC_H - -int wifi_kic_register(struct slsi_dev *sdev); -void wifi_kic_unregister(void); - -#endif /* #ifndef __KIC_H */ diff --git a/drivers/net/wireless/scsc/log_clients.c b/drivers/net/wireless/scsc/log_clients.c deleted file mode 100755 index 388c02d5d072..000000000000 --- a/drivers/net/wireless/scsc/log_clients.c +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "dev.h" -#include "debug.h" -#include "udi.h" -#include "log_clients.h" -#include "unifiio.h" - -/* These functions should NOT be called from interrupt context */ -/* It is supposed to be called from process context, or - * NET_TX_SOFTIRQ - with BHs disabled and interrupts disabled - */ -/* Do not sleep */ - -void slsi_log_clients_log_signal_safe(struct slsi_dev *sdev, struct sk_buff *skb, u32 direction) -{ - struct list_head *pos, *n; - struct slsi_log_client *log_client; - int dir = (direction == SLSI_LOG_DIRECTION_FROM_HOST) ? UDI_FROM_HOST : UDI_TO_HOST; - - spin_lock_bh(&sdev->log_clients.log_client_spinlock); - list_for_each_safe(pos, n, &sdev->log_clients.log_client_list) { - log_client = list_entry(pos, struct slsi_log_client, q); - log_client->log_client_cb(log_client, skb, dir); - } - spin_unlock_bh(&sdev->log_clients.log_client_spinlock); -} - -void slsi_log_clients_init(struct slsi_dev *sdev) -{ - INIT_LIST_HEAD(&sdev->log_clients.log_client_list); - spin_lock_init(&sdev->log_clients.log_client_spinlock); -} - -/* The arg called "filter" will eventually be passed to kfree(). - * - so pass a NULL if you are not doing any filtering - */ -int slsi_log_client_register(struct slsi_dev *sdev, void *log_client_ctx, - int (*log_client_cb)(struct slsi_log_client *, struct sk_buff *, int), - char *filter, int min_signal_id, int max_signal_id) -{ - struct slsi_log_client *log_client; - int first_in_list = 0; - - first_in_list = list_empty(&sdev->log_clients.log_client_list); - log_client = kmalloc(sizeof(*log_client), GFP_KERNEL); - if (log_client == NULL) - return -ENOMEM; - - log_client->min_signal_id = min_signal_id; - log_client->max_signal_id = max_signal_id; - log_client->signal_filter = filter; - log_client->log_client_ctx = log_client_ctx; - log_client->log_client_cb = log_client_cb; - - /* Add to tail of log queue */ - spin_lock_bh(&sdev->log_clients.log_client_spinlock); - list_add_tail(&log_client->q, &sdev->log_clients.log_client_list); - spin_unlock_bh(&sdev->log_clients.log_client_spinlock); - - return 0; -} - -void slsi_log_clients_terminate(struct slsi_dev *sdev) -{ - /* If the driver is configured to try and terminate UDI user space - * applications, the following will try to do so. - */ - if (*sdev->term_udi_users) { - int num_polls_left = 50; - unsigned int timeout_ms = 4; - - slsi_log_client_msg(sdev, UDI_DRV_UNLOAD_IND, 0, NULL); - - /* Poll until all refs have gone away or timeout */ - while (slsi_check_cdev_refs() && num_polls_left) { - msleep(timeout_ms); - num_polls_left--; - } - } -} - -void slsi_log_client_msg(struct slsi_dev *sdev, u16 event, u32 event_data_length, const u8 *event_data) -{ - struct list_head *pos, *n; - struct slsi_log_client *log_client; - - spin_lock_bh(&sdev->log_clients.log_client_spinlock); - list_for_each_safe(pos, n, &sdev->log_clients.log_client_list) { - log_client = list_entry(pos, struct slsi_log_client, q); - spin_unlock_bh(&sdev->log_clients.log_client_spinlock); - if (slsi_kernel_to_user_space_event(log_client, event, event_data_length, event_data)) - SLSI_WARN(sdev, "Failed to send event(0x%.4X) to UDI client 0x%p\n", event, log_client); - spin_lock_bh(&sdev->log_clients.log_client_spinlock); - } - spin_unlock_bh(&sdev->log_clients.log_client_spinlock); -} - -void slsi_log_client_unregister(struct slsi_dev *sdev, void *log_client_ctx) -{ - struct list_head *pos, *n; - struct slsi_log_client *log_client; - - spin_lock_bh(&sdev->log_clients.log_client_spinlock); - list_for_each_safe(pos, n, &sdev->log_clients.log_client_list) { - log_client = list_entry(pos, struct slsi_log_client, q); - if (log_client->log_client_ctx == log_client_ctx) { - kfree(log_client->signal_filter); - list_del(pos); - kfree(log_client); - } - } - spin_unlock_bh(&sdev->log_clients.log_client_spinlock); -} diff --git a/drivers/net/wireless/scsc/log_clients.h b/drivers/net/wireless/scsc/log_clients.h deleted file mode 100644 index e5b809ff9ea7..000000000000 --- a/drivers/net/wireless/scsc/log_clients.h +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_LOG_CLIENTS_H__ -#define __SLSI_LOG_CLIENTS_H__ - -#include - -struct slsi_dev; - -struct slsi_log_client { - struct list_head q; - void *log_client_ctx; - int (*log_client_cb)(struct slsi_log_client *, struct sk_buff *, int); - int min_signal_id; - int max_signal_id; - char *signal_filter; -}; - -struct slsi_log_clients { - /* a std spinlock */ - spinlock_t log_client_spinlock; - struct list_head log_client_list; -}; - -#define SLSI_LOG_DIRECTION_FROM_HOST 0 -#define SLSI_LOG_DIRECTION_TO_HOST 1 - -void slsi_log_clients_init(struct slsi_dev *sdev); -int slsi_log_client_register(struct slsi_dev *sdev, void *log_client_ctx, - int (*log_client_cb)(struct slsi_log_client *, struct sk_buff *, int), - char *filter, int min_signal_id, int max_signal_id); - -void slsi_log_client_unregister(struct slsi_dev *sdev, void *log_client_ctx); -void slsi_log_client_msg(struct slsi_dev *sdev, u16 event, u32 event_data_length, const u8 *event_data); -void slsi_log_clients_log_signal_safe(struct slsi_dev *sdev, struct sk_buff *skb, u32 direction); -static inline void slsi_log_clients_log_signal_fast(struct slsi_dev *sdev, struct slsi_log_clients *log_clients, struct sk_buff *skb, u32 direction) -{ - /* list_empty() is unsafe but fast - * slsi_log_clients_log_signal_safe() will make sure all is good - */ - if (!list_empty(&log_clients->log_client_list)) - slsi_log_clients_log_signal_safe(sdev, skb, direction); -} - -void slsi_log_clients_terminate(struct slsi_dev *sdev); - -#endif /*__SLSI_LOG_CLIENTS_H__*/ diff --git a/drivers/net/wireless/scsc/mbulk.c b/drivers/net/wireless/scsc/mbulk.c deleted file mode 100644 index 037c3212afea..000000000000 --- a/drivers/net/wireless/scsc/mbulk.c +++ /dev/null @@ -1,453 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ -#include -#include -#include "mbulk.h" -#include "hip4_sampler.h" - -#include "debug.h" - -#define MBULK_DEBUG - -/* mbulk descriptor is aligned to 64 bytes considering the host processor's - * cache line size - */ -#define MBULK_ALIGN (64) -#define MBULK_IS_ALIGNED(s) (((uintptr_t)(s) & (MBULK_ALIGN - 1)) == 0) -#define MBULK_SZ_ROUNDUP(s) round_up(s, MBULK_ALIGN) - -/* a magic number to allocate the remaining buffer to the bulk buffer - * in a segment. Used in chained mbulk allocation. - */ -#define MBULK_DAT_BUFSZ_REQ_BEST_MAGIC ((u32)(-2)) - -DEFINE_SPINLOCK(mbulk_pool_lock); - -static inline void mbulk_debug(struct mbulk *m) -{ - (void)m; /* may be unused */ - SLSI_DBG1_NODEV(SLSI_MBULK, "m->next_offset %p: %d\n", &m->next_offset, m->next_offset); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->flag %p: %d\n", &m->flag, m->flag); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->clas %p: %d\n", &m->clas, m->clas); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->pid %p: %d\n", &m->pid, m->pid); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->refcnt %p: %d\n", &m->refcnt, m->refcnt); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->dat_bufsz %p: %d\n", &m->dat_bufsz, m->dat_bufsz); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->sig_bufsz %p: %d\n", &m->sig_bufsz, m->sig_bufsz); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->len %p: %d\n", &m->len, m->len); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->head %p: %d\n", &m->head, m->head); - SLSI_DBG1_NODEV(SLSI_MBULK, "m->chain_next_offset %p: %d\n", &m->chain_next_offset, m->chain_next_offset); -} - -/* mbulk pool */ -struct mbulk_pool { - bool valid; /** is valid */ - u8 pid; /** pool id */ - struct mbulk *free_list; /** head of free segment list */ - int free_cnt; /** current number of free segments */ - int usage[MBULK_CLASS_MAX]; /** statistics of usage per mbulk clas*/ - char *base_addr; /** base address of the pool */ - char *end_addr; /** exclusive end address of the pool */ - mbulk_len_t seg_size; /** segment size in bytes "excluding" struct mbulk */ - u8 guard; /** pool guard **/ -#ifdef MBULK_DEBUG - int tot_seg_num; /** total number of segments in this pool */ -#endif -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - int minor; -#endif -}; - -/* get a segment from a pool */ -static inline struct mbulk *mbulk_pool_get(struct mbulk_pool *pool, enum mbulk_class clas) -{ - struct mbulk *m; - u8 guard = pool->guard; - - spin_lock_bh(&mbulk_pool_lock); - m = pool->free_list; - - if (m == NULL || pool->free_cnt <= guard) { /* guard */ - spin_unlock_bh(&mbulk_pool_lock); - return NULL; - } - - pool->free_cnt--; - pool->usage[clas]++; - - SCSC_HIP4_SAMPLER_MBULK(pool->minor, (pool->free_cnt & 0x100) >> 8, (pool->free_cnt & 0xff), clas); - - if (m->next_offset == 0) - pool->free_list = NULL; - else - pool->free_list = (struct mbulk *)((uintptr_t)pool->free_list + m->next_offset); - - memset(m, 0, sizeof(*m)); - m->pid = pool->pid; - m->clas = clas; - - spin_unlock_bh(&mbulk_pool_lock); - return m; -} - -/* put a segment to a pool */ -static inline void mbulk_pool_put(struct mbulk_pool *pool, struct mbulk *m) -{ - if (m->flag == MBULK_F_FREE) - return; - - spin_lock_bh(&mbulk_pool_lock); - pool->usage[m->clas]--; - pool->free_cnt++; - - SCSC_HIP4_SAMPLER_MBULK(pool->minor, (pool->free_cnt & 0x100) >> 8, (pool->free_cnt & 0xff), m->clas); - m->flag = MBULK_F_FREE; - if (pool->free_list != NULL) - m->next_offset = (uintptr_t)pool->free_list - (uintptr_t)m; - else - m->next_offset = 0; - pool->free_list = m; - spin_unlock_bh(&mbulk_pool_lock); -} - -/** mbulk pool configuration */ -struct mbulk_pool_config { - mbulk_len_t seg_sz; /** segment size "excluding" struct mbulk */ - int seg_num; /** number of segments. If -1, all remaining space is used */ -}; - -/** mbulk pools */ -static struct mbulk_pool mbulk_pools[MBULK_POOL_ID_MAX]; - -/** - * allocate a mbulk segment from the pool - * - * Note that the refcnt would be zero if \dat_bufsz is zero, as there is no - * allocated bulk data. - * If \dat_bufsz is \MBULK_DAT_BUFSZ_REQ_BEST_MAGIC, then this function - * allocates all remaining buffer space to the bulk buffer. - * - */ -static struct mbulk *mbulk_seg_generic_alloc(struct mbulk_pool *pool, - enum mbulk_class clas, size_t sig_bufsz, size_t dat_bufsz) -{ - struct mbulk *m; - - if (pool == NULL) - return NULL; - - /* get a segment from the pool */ - m = mbulk_pool_get(pool, clas); - if (m == NULL) - return NULL; - - /* signal buffer */ - m->sig_bufsz = (mbulk_len_t)sig_bufsz; - if (sig_bufsz) - m->flag = MBULK_F_SIG; - - /* data buffer. - * Note that data buffer size can be larger than the requested. - */ - m->head = m->sig_bufsz; - if (dat_bufsz == 0) { - m->dat_bufsz = 0; - m->refcnt = 0; - } else if (dat_bufsz == MBULK_DAT_BUFSZ_REQ_BEST_MAGIC) { - m->dat_bufsz = pool->seg_size - m->sig_bufsz; - m->refcnt = 1; - } else { - m->dat_bufsz = (mbulk_len_t)dat_bufsz; - m->refcnt = 1; - } - - mbulk_debug(m); - return m; -} - -int mbulk_pool_get_free_count(u8 pool_id) -{ - struct mbulk_pool *pool; - int num_free; - - if (pool_id >= MBULK_POOL_ID_MAX) { - WARN_ON(pool_id >= MBULK_POOL_ID_MAX); - return -EIO; - } - - spin_lock_bh(&mbulk_pool_lock); - pool = &mbulk_pools[pool_id]; - - if (!pool->valid) { - WARN_ON(!pool->valid); - spin_unlock_bh(&mbulk_pool_lock); - return -EIO; - } - - num_free = pool->free_cnt; - spin_unlock_bh(&mbulk_pool_lock); - - return num_free; -} - -/** - * Allocate a bulk buffer with an in-lined signal buffer - * - * A mbulk segment is allocated from the given the pool, if its size - * meeting the requested size. - * - */ -struct mbulk *mbulk_with_signal_alloc_by_pool(u8 pool_id, u16 colour, - enum mbulk_class clas, size_t sig_bufsz_req, size_t dat_bufsz) -{ - struct mbulk_pool *pool; - size_t sig_bufsz; - size_t tot_bufsz; - struct mbulk *m_ret; - - /* data buffer should be aligned */ - sig_bufsz = MBULK_SIG_BUFSZ_ROUNDUP(sizeof(struct mbulk) + sig_bufsz_req) - sizeof(struct mbulk); - - if (pool_id >= MBULK_POOL_ID_MAX) { - WARN_ON(pool_id >= MBULK_POOL_ID_MAX); - return NULL; - } - - pool = &mbulk_pools[pool_id]; - - if (!pool->valid) { - WARN_ON(!pool->valid); - return NULL; - } - - /* check if this pool meets the size */ - tot_bufsz = sig_bufsz + dat_bufsz; - if (dat_bufsz != MBULK_DAT_BUFSZ_REQ_BEST_MAGIC && - pool->seg_size < tot_bufsz) - return NULL; - - m_ret = mbulk_seg_generic_alloc(pool, clas, sig_bufsz, dat_bufsz); - /* Colour the mbulk */ - if (m_ret) { - /* Use pool id for coding vif and peer_id */ - m_ret->pid = m_ret->pid | (colour & 0xfe); - /* Code AC queue at the [7:6] bits */ - m_ret->clas = m_ret->clas | ((colour & 0x300) >> 2); - } - return m_ret; -} - -#ifdef MBULK_SUPPORT_SG_CHAIN -/** - * allocate a chained mbulk buffer from a specific mbulk pool - * - */ -struct mbulk *mbulk_chain_with_signal_alloc_by_pool(u8 pool_id, - enum mbulk_class clas, size_t sig_bufsz, size_t dat_bufsz) -{ - size_t tot_len; - struct mbulk *m, *head, *pre; - - head = mbulk_with_signal_alloc_by_pool(pool_id, clas, sig_bufsz, - MBULK_DAT_BUFSZ_REQ_BEST_MAGIC); - if (head == NULL || MBULK_SEG_TAILROOM(head) >= dat_bufsz) - return head; - - head->flag |= (MBULK_F_CHAIN_HEAD | MBULK_F_CHAIN); - tot_len = MBULK_SEG_TAILROOM(head); - pre = head; - - while (tot_len < dat_bufsz) { - m = mbulk_with_signal_alloc_by_pool(pool_id, clas, 0, - MBULK_DAT_BUFSZ_REQ_BEST_MAGIC); - if (m == NULL) - break; - /* all mbulk in this chain has an attribue, MBULK_F_CHAIN */ - m->flag |= MBULK_F_CHAIN; - tot_len += MBULK_SEG_TAILROOM(m); - pre->chain_next = m; - pre = m; - } - - if (tot_len < dat_bufsz) { - mbulk_chain_free(head); - return NULL; - } - - return head; -} - -/** - * free a chained mbulk - */ -void mbulk_chain_free(struct mbulk *sg) -{ - struct mbulk *chain_next, *m; - - /* allow null pointer */ - if (sg == NULL) - return; - - m = sg; - while (m != NULL) { - chain_next = m->chain_next; - - /* is not scatter-gather anymore */ - m->flag &= ~(MBULK_F_CHAIN | MBULK_F_CHAIN_HEAD); - mbulk_seg_free(m); - - m = chain_next; - } -} - -/** - * get a tail mbulk in the chain - * - */ -struct mbulk *mbulk_chain_tail(struct mbulk *m) -{ - while (m->chain_next != NULL) - m = m->chain_next; - return m; -} - -/** - * total buffer size in a chanied mbulk - * - */ -size_t mbulk_chain_bufsz(struct mbulk *m) -{ - size_t tbufsz = 0; - - while (m != NULL) { - tbufsz += m->dat_bufsz; - m = m->chain_next; - } - - return tbufsz; -} - -/** - * total data length in a chanied mbulk - * - */ -size_t mbulk_chain_tlen(struct mbulk *m) -{ - size_t tlen = 0; - - while (m != NULL) { - tlen += m->len; - m = m->chain_next; - } - - return tlen; -} -#endif /*MBULK_SUPPORT_SG_CHAIN*/ - -/** - * add a memory zone to a mbulk pool list - * - */ -#ifdef CONFIG_SCSC_WLAN_DEBUG -int mbulk_pool_add(u8 pool_id, char *base, char *end, size_t seg_size, u8 guard, int minor) -#else -int mbulk_pool_add(u8 pool_id, char *base, char *end, size_t seg_size, u8 guard) -#endif -{ - struct mbulk_pool *pool; - struct mbulk *next; - size_t byte_per_block; - - if (pool_id >= MBULK_POOL_ID_MAX) { - WARN_ON(pool_id >= MBULK_POOL_ID_MAX); - return -EIO; - } - - pool = &mbulk_pools[pool_id]; - - if (!MBULK_IS_ALIGNED(base)) { - WARN_ON(!MBULK_IS_ALIGNED(base)); - return -EIO; - } - - /* total required memory per block */ - byte_per_block = MBULK_SZ_ROUNDUP(sizeof(struct mbulk) + seg_size); - - /* init pool structure */ - memset(pool, 0, sizeof(*pool)); - pool->pid = pool_id; - pool->base_addr = base; - pool->end_addr = end; - pool->seg_size = (mbulk_len_t)(byte_per_block - sizeof(struct mbulk)); - pool->guard = guard; - - /* allocate segments */ - next = (struct mbulk *)base; - while (((uintptr_t)next + byte_per_block) <= (uintptr_t)end) { - memset(next, 0, sizeof(struct mbulk)); - next->pid = pool_id; - - /* add to the free list */ - if (pool->free_list == NULL) - next->next_offset = 0; - else - next->next_offset = (uintptr_t)pool->free_list - (uintptr_t)next; - next->flag = MBULK_F_FREE; - pool->free_list = next; -#ifdef MBULK_DEBUG - pool->tot_seg_num++; -#endif - pool->free_cnt++; -/* TOM.. BUG. */ - next = (struct mbulk *)((uintptr_t)next + byte_per_block); - } - - pool->valid = (pool->free_cnt) ? true : false; -#ifdef CONFIG_SCSC_WLAN_DEBUG - pool->minor = minor; -#endif - return 0; -} - -/** - * add mbulk pools in MIF address space - */ -void mbulk_pool_dump(u8 pool_id, int max_cnt) -{ - struct mbulk_pool *pool; - struct mbulk *m; - int cnt = max_cnt; - - pool = &mbulk_pools[pool_id]; - m = pool->free_list; - while (m != NULL && cnt--) - m = (m->next_offset == 0) ? NULL : - (struct mbulk *)(pool->base_addr + m->next_offset); -} - -/** - * free a mbulk in the virtual host - */ -void mbulk_free_virt_host(struct mbulk *m) -{ - u8 pool_id; - struct mbulk_pool *pool; - - if (m == NULL) - return; - - /* Remove colour */ - pool_id = m->pid & 0x1; - - pool = &mbulk_pools[pool_id]; - - if (!pool->valid) { - WARN_ON(!pool->valid); - return; - } - - /* put to the pool */ - mbulk_pool_put(pool, m); -} diff --git a/drivers/net/wireless/scsc/mbulk.h b/drivers/net/wireless/scsc/mbulk.h deleted file mode 100644 index 60379da84318..000000000000 --- a/drivers/net/wireless/scsc/mbulk.h +++ /dev/null @@ -1,523 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef __MBULK_H__ -#define __MBULK_H__ - -/** - * mbulk(bulk memory) API - * - * This header file describes APIs of the bulk memory management. - * The diagram below is an example of a mbulk buffer with one - * segment (i.e. not a chained mbulk). - * - * sig_bufsz - * |<-------->| - * | |<--------- dat_bufsz ---------->| - * +--------------------------------------------------+ - * | mbulk| signal | bulk buffer | - * +-------------------------+---------------+--------+ - * | | | valid data | | - * | | |<--------+---->| | - * | | | mbulk_tlen(m) | | - * | |<----->| | |<------>| - * | mbulk_headroom(m)| | mbulk_tailroom(m) - * | | | - * | |-- off -->| - * v v | - * mbulk_get_sig(m) mbulk_dat(m) | - * v - * mbulk_dat_at(m,off) - * - * In general, all clients are supposed to use only mbulk_xxx() APIs (but not - * mbulk_seg_xxx() APIs), as they can handle S/G chained mbulk as well. - * But as of now, specially in Condor, S/G chained mbulk is not supported, - * which means the most of mbulk_xxx() would be wrappers of mbulk_seg_xxx(). - * - * An in-lined signal buffer can be allocated along with a mbulk buffer. - * There is no direct life-cycle relationship between the signal and the - * associated mbulk in this case, which means that the signal buffer should be - * de-allocated independently of the mbulk buffer. - * - */ - -/** - * bulk buffer descriptor - */ -struct mbulk; - -/** - * mbulk host pool ID - */ -#define MBULK_POOL_ID_DATA (0) -#define MBULK_POOL_ID_CTRL (1) -#define MBULK_POOL_ID_MAX (2) - -/** - * mbulk buffer classification - * - * Note that PACKED attribute is added to enum definition so that - * compiler assigns the smallest integral type (u8). - */ -enum mbulk_class { - MBULK_CLASS_CONTROL = 0, - MBULK_CLASS_HOSTIO = 1, - MBULK_CLASS_DEBUG = 2, - - MBULK_CLASS_FROM_HOST_DAT = 3, - MBULK_CLASS_FROM_HOST_CTL = 4, - MBULK_CLASS_FROM_RADIO = 5, - MBULK_CLASS_DPLP = 6, - MBULK_CLASS_OTHERS = 7, - MBULK_CLASS_FROM_RADIO_FORWARDED = 8, - MBULK_CLASS_MAX -} __packed; - -/** - * The private definition of mbulk structure is included here - * so that its members can be directly accessed, and the access - * codes can be in-lined by the compiler. - * But client codes are not supposed to directly refer to mbulk - * members, nor use mbulk_seg_xxx() functions. Only modules handling - * mbulk scatter/gather chain would directly use mulk_seg_xxx() APIs. - */ -#include "mbulk_def.h" - -/** - * Get the bulk data reference counter - * - * After a bulk buffer with non-zero data buffer size is created, - * the reference counter is set to one. Each time it is duplicated, - * its reference counter would be increased. - * - * Note that the reference counter is initialized to zero if a signal - * is created from mbulk pool but with zero data buffer size, as there - * is no data buffer. - */ -static inline int mbulk_refcnt(const struct mbulk *m) -{ - return MBULK_SEG_REFCNT(m); -} - -/** - * Get the bulk data buffer size - * - */ -static inline int mbulk_buffer_size(const struct mbulk *m) -{ - return MBULK_SEG_DAT_BUFSIZE(m); -} - -/** - * Check if mbulk has an in-lined signal buffer - * - */ -static inline bool mbulk_has_signal(const struct mbulk *m) -{ - return MBULK_SEG_HAS_SIGNAL(m); -} - -/** - * Set mbulk to be read-only - */ -static inline void mbulk_set_readonly(struct mbulk *m) -{ - MBULK_SEG_SET_READONLY(m); -} - -/** - * is mbulk read-only - */ -static inline bool mbulk_is_readonly(const struct mbulk *m) -{ - return MBULK_SEG_IS_READONLY(m); -} - -/** - * check if mbulk is a scatter/gather chained buffer - * - */ -static inline bool mbulk_is_sg(const struct mbulk *m) -{ - return MBULK_SEG_IS_CHAIN_HEAD(m); -} - -/** - * check if mbulk is a part of scatter/gather chained buffer - * - */ -static inline bool mbulk_is_chained(const struct mbulk *m) -{ - return MBULK_SEG_IS_CHAINED(m); -} - -/** - * Allocate a bulk buffer with an in-lined signal buffer - * - * Only one mbulk segment is used for allocation starting from the - * mbulk pool with the smallest segment size. If no segment fitting - * the requested size, then return NULL without trying to create - * a chained buffer. - * - */ -struct mbulk *mbulk_with_signal_alloc(enum mbulk_class clas, size_t sig_bufsz, - size_t dat_bufsz); -/** - * Allocate a bulk buffer with an in-lined signal buffer - * - * A mbulk segment is allocated from the given the pool, if its size - * meeting the requested size. - * - */ -struct mbulk *mbulk_with_signal_alloc_by_pool(u8 pool_id, u16 colour, - enum mbulk_class clas, size_t sig_bufsz, size_t dat_bufsz); - -/** - * Get the number of free mbulk slots in a pool - * - * Returns the number of mbulk slots available in a given pool. - */ -int mbulk_pool_get_free_count(u8 pool_id); - -/** - * Get a signal buffer address - * - * Given a mbulk buffer, returns a signal buffer address. - * - * @param m mbulk - * @return in-lined signal buffer - */ -static inline void *mbulk_get_seg(const struct mbulk *m) -{ - return (void *)MBULK_SEG_B(m); -} - -/** - * Get a signal buffer address - * - * Given a mbulk buffer, returns a signal buffer address if any in-lined - * signal buffer. - * - */ -static inline void *mbulk_get_signal(const struct mbulk *m) -{ - bool ret = false; - - ret = mbulk_has_signal(m); - - return ret ? mbulk_get_seg(m) : NULL; -} - -/** - * Allocate a bulk buffer - * - * Only one mbulk segment is used for allocation starting from the - * mbulk pool with the smallest segment size. If no segment fitting - * the requested size, then return NULL without trying to create - * a chained buffer. - * - */ -static inline struct mbulk *mbulk_alloc(enum mbulk_class clas, size_t dat_bufsz) -{ - return mbulk_with_signal_alloc(clas, 0, dat_bufsz); -} - -/** - * free mbulk buffer - * - * After checking the bulk reference counter, this function return the buffer - * to the mbulk pool if it is zero. Note that this doesn't free the in-lined - * signal buffer. - */ -static inline void mbulk_free(struct mbulk *m) -{ - mbulk_seg_free(m); -} - -/** - * get bulk buffer address for read or write access - * - * The address is the buffer address after the headroom in the mbulk segment. - * Note that this function can only be used to access the data in the same - * segment, including a segment in the mbulk chain (for example, to access - * the 802.11 header of A-MSDU). - * - */ -static inline void *mbulk_dat_rw(const struct mbulk *m) -{ - WARN_ON(MBULK_SEG_IS_READONLY(m)); - return MBULK_SEG_DAT(m); -} - -/** - * get bulk buffer address for read-only - * - * The address is the buffer address after the headroom in the mbulk segment. - * Note that this function can only be used to access the data in the same - * segment, including a segment in the mbulk chain (for example, to access - * the 802.11 header of A-MSDU). - * - */ -static inline const void *mbulk_dat_r(const struct mbulk *m) -{ - return (const void *)MBULK_SEG_DAT(m); -} - -/** - * get bulk buffer address at the offset for read or write access - * - */ -static inline void *mbulk_dat_at_rw(const struct mbulk *m, size_t off) -{ - WARN_ON(MBULK_SEG_IS_READONLY(m)); - return MBULK_SEG_DAT_AT(m, off); -} - -/** - * get bulk buffer address at the offset for read access - * - */ -static inline /*const*/ void *mbulk_dat_at_r(const struct mbulk *m, size_t off) -{ - return (/*const */ void *)MBULK_SEG_DAT_AT(m, off); -} - -/** - * get valid data length - * - */ -static inline size_t mbulk_tlen(const struct mbulk *m) -{ - return MBULK_SEG_LEN(m); -} - -/** - * get headroom - * - */ -static inline size_t mbulk_headroom(const struct mbulk *m) -{ - return MBULK_SEG_HEADROOM(m); -} - -static inline size_t mbulk_tailroom(const struct mbulk *m) -{ - return MBULK_SEG_TAILROOM(m); -} - -/** - * reserve headroom - * - * Note this API should be called right after mbulk is created or the valid - * data length is zero. - * - */ -static inline bool mbulk_reserve_head(struct mbulk *m, size_t headroom) -{ - return mbulk_seg_reserve_head(m, headroom); -} - -/** - * adjust the valid data range - * - * headroom would be placed after the signal buffer (or mbuf descriptor if - * no in-lined signal), and the valid data length is set to \len. - * - */ -static inline bool mbulk_adjust_range(struct mbulk *m, size_t headroom, size_t len) -{ - return mbulk_seg_adjust_range(m, headroom, len); -} - -/** - * extend the data range at the head - * - * The headroom would be reduced, and the data range is extended. - * To prepend data in the head, the headroom should have been reserved before. - * - */ -static inline bool mbulk_prepend_head(struct mbulk *m, size_t more) -{ - return mbulk_seg_prepend_head(m, more); -} - -/** - * extend the data at the tail - * - * Data range is expanded towards the tail. - * - */ -static inline bool mbulk_append_tail(struct mbulk *m, size_t more) -{ - return mbulk_seg_append_tail(m, more); -} - -/** - * trim data at the head - * - * The headroom would be increased, and the valid data range is reduced - * accordingly. - * - */ -static inline bool mbulk_trim_head(struct mbulk *m, size_t less) -{ - return mbulk_seg_trim_head(m, less); -} - -/** - * trim data at the tail - * - * The data length would be reduced. - * - */ -static inline bool mbulk_trim_tail(struct mbulk *m, size_t less) -{ - return mbulk_seg_trim_tail(m, less); -} - -/** - * duplicate a mbulk - * - * There is no data copy. but the referece counter of the orignal mbulk is - * increased by one. - * - */ -static inline struct mbulk *mbulk_duplicate(struct mbulk *m) -{ - return mbulk_seg_duplicate(m); -} - -/** - * clone a mbulk - * - * New mbulk buffer is created, and contents are copied. The signal is copied - * only when \copy_sig is TRUE. - * - */ -static inline struct mbulk *mbulk_clone(const struct mbulk *m, enum mbulk_class clas, - bool copy_sig) -{ - return mbulk_seg_clone(m, clas, copy_sig); -} - -/** - * allocate a signal buffer from mbulk pool - * - */ -void *msignal_alloc(size_t sig_sz); - -/** - * free a signal buffer created from mbulk pool - * - */ -void msignal_free(void *sig); - -/** - * get mbulk descriptor given a signal buffer address - * - */ -struct mbulk *msignal_to_mbulk(void *sig); - -/** - * get next chained mbulk in a scatter/gathered list - */ -static inline scsc_mifram_ref mbulk_chain_next(struct mbulk *m) -{ - return MBULK_SEG_CHAIN_NEXT(m); -} - -#ifdef MBULK_SUPPORT_SG_CHAIN -/** - * Scatter/Gather Chained Mbulk APIs - * ================================= - */ - -/** - * allocate a chained mbulk buffer from a specific mbulk pool - * - */ -struct mbulk *mbulk_chain_with_signal_alloc_by_pool(u8 pool_id, - enum mbulk_class clas, size_t sig_bufsz, size_t dat_bufsz); - -/** - * free a chained mbulk - */ -void mbulk_chain_free(struct mbulk *sg); - -/** - * get a tail mbulk in the chain - * - */ -struct mbulk *mbulk_chain_tail(struct mbulk *m); - -/** - * total buffer size in a chanied mbulk - * - */ -size_t mbulk_chain_bufsz(struct mbulk *m); - -/** - * total data length in a chanied mbulk - * - */ -size_t mbulk_chain_tlen(struct mbulk *m); - -/** - * get a number of mbulk segments in a chained mbulk - */ -static inline int mbulk_chain_num(const struct mbulk *m) -{ - if (mbulk_is_sg(m)) { - int n = 0; - - while (m != NULL) { - n++; - m = m->chain_next; - } - return n; - } - return 1; -} - -/* NOT IMPLEMENTED YET. */ -void *mbulk_chain_access(struct mbulk *m, size_t off, char *local_buf, size_t local_bufsz); -void *mbulk_chain_writeback(struct mbulk *m, size_t off, char *local_buf, size_t local_bufsz); -void *mbulk_chain_copy_from(struct mbulk *m, size_t off, char *buf, int len); -void *mbulk_chain_copy_to(struct mbulk *m, size_t off, char *buf, int len); -#endif /*MBULK_SUPPORT_SG_CHAIN*/ - -/** - * init mbulk library - */ -/*extern void init_mbulk(void);*/ -void init_mbulk(void *mem, size_t pool_size); - -/** - * add a memory zone to a mbulk pool list - * - */ -#ifdef CONFIG_SCSC_WLAN_DEBUG -int mbulk_pool_add(u8 pool_id, char *base, char *end, size_t seg_size, u8 guard, int minor); -#else -int mbulk_pool_add(u8 pool_id, char *base, char *end, size_t buf_size, u8 guard); -#endif -/** - * check sanity of a mbulk pool - */ -void mbulk_pool_check_sanity(u8 pool_id); - -/** - * configure the handler which returning the buffer to the host - */ -void mbulk_set_handler_return_host_mbulk(void (*free_host_buf)(struct mbulk *m)); - -/** - * free a mbulk in the virtual host - */ -void mbulk_free_virt_host(struct mbulk *m); -void mbulk_pool_dump(u8 pool_id, int max_cnt); - -#endif /*__MBULK_H__*/ diff --git a/drivers/net/wireless/scsc/mbulk_def.h b/drivers/net/wireless/scsc/mbulk_def.h deleted file mode 100644 index d3fff5e15284..000000000000 --- a/drivers/net/wireless/scsc/mbulk_def.h +++ /dev/null @@ -1,171 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef __MBULK_DEF_H__ -#define __MBULK_DEF_H__ - -#include -#include - -/** - * mbulk - * - * The mbulk supports .... - */ - -/* MIF_HIP_CFG_BLUK_BUFFER_ALIGNE = 4 - * Hence, data buffer is always aligned to 4. - */ -#define MBULK_SIG_BUFSZ_ROUNDUP(sig_bufsz) round_up(sig_bufsz, 4) - -/** - * bulk memory descriptor, managing semgments allocated from mbulk pools - * - * mbulk is defined in public header, to avoid the function call dummy operations... - * Privae variables staring with __ should be not be referred by the client - * codes. - * - * mbulk structure is shared with the host. Hence the structure should be packed. - * data buffer size in byte - * - * This could be duplicated as the buffer size can be calculated from - * pool block size. There are two reasons why the data buffer size is - * set in the descritpor: - * - if mbulk comes from the host, the firmware is not aware of its pool - * configuration - * - if the data buffer is less than the block size in the pool, it's more - * cache efficient to flush only the data buffer area - * probably the firwmare has to invalidate the entire block ? - * - */ -typedef u16 mbulk_len_t; -struct mbulk { - scsc_mifram_ref next_offset; /** next mbulk offset */ - u8 flag; /** mbulk flags */ - enum mbulk_class clas; /** bulk buffer classification */ - u8 pid; /** mbulk pool id */ - u8 refcnt; /** reference counter of bulk buffer */ - mbulk_len_t dat_bufsz; /** data buffer size in byte */ - mbulk_len_t sig_bufsz; /** signal buffer size in byte */ - mbulk_len_t len; /** valid data length */ - mbulk_len_t head; /** start offset of data after mbulk structure */ - scsc_mifram_ref chain_next_offset; /** chain next mbulk offset */ -} __packed; - -/* mbulk flags */ -#define MBULK_F_SIG (1 << 0) /** has a signal after mbulk descriptor*/ -#define MBULK_F_READONLY (1 << 1) /** is read-only */ -#define MBULK_F_OBOUND (1 << 2) /** other CPU(host) owns the buffer */ -#define MBULK_F_WAKEUP (1 << 3) /** frame waking up the host */ -#define MBULK_F_FREE (1 << 5) /** mbulk alreay freed */ -#define MBULK_F_CHAIN_HEAD (1 << 6) /** is an head in scatter/gather chain */ -#define MBULK_F_CHAIN (1 << 7) /** is scatter/gather chain */ - -/* TODO: Define max number of chained mbulk */ -#define MBULK_MAX_CHAIN 16 -/* the buffer address just after mbulk descriptor */ -#define MBULK_SEG_B(m) ((uintptr_t)(m) + sizeof(struct mbulk)) - -/* raw buffer size of mbulk segment including struct mbulk */ -#define MBULK_SEG_RAW_BUFSZ(m) (sizeof(struct mbulk) + (m)->sig_bufsz + (m)->dat_bufsz) - -/* operations against "a" mbulk segment. */ -#define MBULK_SEG_NEXT(m) ((m)->next_offset) -#define MBULK_SEG_REFCNT(m) ((m)->refcnt) -#define MBULK_SEG_HAS_SIGNAL(m) ((m)->flag & MBULK_F_SIG) -#define MBULK_SEG_CHAIN_NEXT(m) ((m)->chain_next_offset) -#define MBULK_SEG_IS_CHAIN_HEAD(m) ((m)->flag & MBULK_F_CHAIN_HEAD) -#define MBULK_SEG_IS_CHAINED(m) ((m)->flag & MBULK_F_CHAIN) - -#define MBULK_SEG_IS_READONLY(m) ((m)->flag & MBULK_F_READONLY) -#define MBULK_SEG_SET_READONLY(m) ((m)->flag |= MBULK_F_READONLY) - -#define MBULK_SEG_DAT(m) ((char *)MBULK_SEG_B(m) + (m)->head) -#define MBULK_SEG_DAT_AT(m, off) ((char *)MBULK_SEG_B(m) + (m)->head + (mbulk_len_t)(off)) -#define MBULK_SEG_DAT_BUFSIZE(m) ((size_t)((m)->dat_bufsz)) -#define MBULK_SEG_SIG_BUFSIZE(m) ((size_t)((m)->sig_bufsz)) -#define MBULK_SEG_LEN(m) ((m)->len) -#define MBULK_SEG_HEADROOM(m) ((size_t)((m)->head - (m)->sig_bufsz)) -#define MBULK_SEG_TAILROOM(m) ((size_t)((m)->dat_bufsz - (MBULK_SEG_HEADROOM(m) + (m)->len))) - -static inline bool mbulk_seg_reserve_head(struct mbulk *m, size_t headroom) -{ - if (WARN_ON(!(m->dat_bufsz >= headroom))) - return false; - m->head += (mbulk_len_t)headroom; - return true; -} - -static inline bool mbulk_seg_adjust_range(struct mbulk *m, size_t headroom, - size_t len) -{ - if (WARN_ON(!(m->dat_bufsz >= (headroom + len)))) - return false; - m->head = m->sig_bufsz + (mbulk_len_t)headroom; - m->len = (mbulk_len_t)len; - return true; -} - -static inline bool mbulk_seg_prepend_head(struct mbulk *m, size_t more) -{ - if (WARN_ON(!(MBULK_SEG_HEADROOM(m) >= more))) - return false; - m->head -= (mbulk_len_t)more; - m->len += (mbulk_len_t)more; - return true; -} - -static inline bool mbulk_seg_append_tail(struct mbulk *m, size_t more) -{ - if (WARN_ON(!(MBULK_SEG_TAILROOM(m) >= more))) - return false; - m->len += (mbulk_len_t)more; - return true; -} - -static inline bool mbulk_seg_trim_head(struct mbulk *m, size_t less) -{ - m->head += (mbulk_len_t)less; - m->len = (m->len <= (mbulk_len_t)less) ? 0 : (m->len - (mbulk_len_t)less); - return true; -} - -static inline bool mbulk_seg_trim_tail(struct mbulk *m, size_t less) -{ - if (WARN_ON(!(m->len >= (mbulk_len_t)less))) - return false; - m->len -= (mbulk_len_t)less; - return true; -} - -/** - * free the bulk buffer of a segment - * - * Simply decrement the bulk reference counter and put to the pool if - * it is zero. Note that the signal buffer is not affected. - * - */ -void mbulk_seg_free(struct mbulk *m); - -/** - * duplicate the bulk buffer of a mbulk segment - * - * This is used to share the read-only bulk buffer. The reference counter is - * increased by one each time it is duplicated. - * - */ -struct mbulk *mbulk_seg_duplicate(struct mbulk *m); - -/** - * clone the bulk buffer of a mbulk segment - * - * A separate mbulk segment is created and the data is copied to it. - * If \copy_sig is true, then the signal is copied as well. - * - */ -struct mbulk *mbulk_seg_clone(const struct mbulk *m, enum mbulk_class clas, bool copy_sig); - -#endif /*__MBULK_DEF_H__*/ diff --git a/drivers/net/wireless/scsc/mgt.c b/drivers/net/wireless/scsc/mgt.c deleted file mode 100755 index 2b8d4f941a96..000000000000 --- a/drivers/net/wireless/scsc/mgt.c +++ /dev/null @@ -1,6127 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include -#include -#include - -#ifdef CONFIG_ARCH_EXYNOS -#include -#endif - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER -#include -#include -#endif - -#include -#include -#include "mgt.h" -#include "debug.h" -#include "mlme.h" -#include "netif.h" -#include "utils.h" -#include "udi.h" -#include "log_clients.h" -#ifdef SLSI_TEST_DEV -#include "unittest.h" -#endif -#include "hip.h" -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif - -#include "procfs.h" -#include "mib.h" -#include "unifiio.h" -#include "ba.h" -#include "scsc_wifi_fcq.h" -#include "cac.h" -#include "cfg80211_ops.h" -#include "nl80211_vendor.h" - -#ifdef CONFIG_SCSC_WLBTD -#include "scsc_wlbtd.h" -#endif -#define CSR_WIFI_SME_MIB2_HOST_PSID_MASK 0x8000 -#define SLSI_DEFAULT_HW_MAC_ADDR "\x00\x00\x0F\x11\x22\x33" -#define MX_WLAN_FILE_PATH_LEN_MAX (128) -#define SLSI_MIB_REG_RULES_MAX (50) -#define SLSI_MIB_MAX_CLIENT (10) -#define SLSI_REG_PARAM_START_INDEX (1) - -static char *mib_file_t = "wlan_t.hcf"; -module_param(mib_file_t, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mib_file_t, "mib data filename"); - -static char *mib_file2_t = "wlan_t_sw.hcf"; -module_param(mib_file2_t, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mib_file2_t, "mib data filename"); - -/* MAC address override. If set to FF's, then - * the address is taken from config files or - * default derived from HW ID. - */ -static char mac_addr_override[] = "ff:ff:ff:ff:ff:ff"; -module_param_string(mac_addr, mac_addr_override, sizeof(mac_addr_override), S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mac_addr_override, "WLAN MAC address override"); - -static int slsi_mib_open_file(struct slsi_dev *sdev, struct slsi_dev_mib_info *mib_info, const struct firmware **fw); -static int slsi_mib_close_file(struct slsi_dev *sdev, const struct firmware *e); -static int slsi_mib_download_file(struct slsi_dev *sdev, struct slsi_dev_mib_info *mib_info); -static int slsi_country_to_index(struct slsi_802_11d_reg_domain *domain_info, const char *alpha2); -static int slsi_mib_initial_get(struct slsi_dev *sdev); -static int slsi_hanged_event_count; -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#define SLSI_MAX_CHAN_5G_BAND 25 -#define SLSI_2G_CHANNEL_ONE 2412 -static int slsi_5ghz_all_channels[] = {5180, 5200, 5220, 5240, 5260, 5280, 5300, 5320, 5500, 5520, - 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5720, - 5745, 5765, 5785, 5805, 5825 }; -#endif - -/* MAC address override stored in /sys/wifi/mac_addr */ -static ssize_t sysfs_show_macaddr(struct kobject *kobj, struct kobj_attribute *attr, - char *buf); -static ssize_t sysfs_store_macaddr(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count); - -static struct kobject *wifi_kobj_ref; -static char sysfs_mac_override[] = "ff:ff:ff:ff:ff:ff"; -static struct kobj_attribute mac_attr = __ATTR(mac_addr, 0660, sysfs_show_macaddr, sysfs_store_macaddr); - -/* Retrieve mac address in sysfs global */ -static ssize_t sysfs_show_macaddr(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return snprintf(buf, sizeof(sysfs_mac_override), "%s", sysfs_mac_override); -} - -/* Update mac address in sysfs global */ -static ssize_t sysfs_store_macaddr(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, - size_t count) -{ - int r; - - SLSI_INFO_NODEV("Override WLAN MAC address %s\n", buf); - - /* size of macaddr string */ - r = sscanf(buf, "%18s", &sysfs_mac_override); - - return (r > 0) ? count : 0; -} - -/* Register sysfs mac address override */ -void slsi_create_sysfs_macaddr(void) -{ - int r; - - wifi_kobj_ref = mxman_wifi_kobject_ref_get(); - pr_info("wifi_kobj_ref: 0x%p\n", wifi_kobj_ref); - - if (wifi_kobj_ref) { - /* Create sysfs file /sys/wifi/mac_addr */ - r = sysfs_create_file(wifi_kobj_ref, &mac_attr.attr); - if (r) { - /* Failed, so clean up dir */ - pr_err("Can't create /sys/wifi/mac_addr\n"); - return; - } - } else { - pr_err("failed to create /sys/wifi/mac_addr\n"); - } -} - -/* Unregister sysfs mac address override */ -void slsi_destroy_sysfs_macaddr(void) -{ - if (!wifi_kobj_ref) - return; - - /* Destroy /sys/wifi/mac_addr file */ - sysfs_remove_file(wifi_kobj_ref, &mac_attr.attr); - - /* Destroy /sys/wifi virtual dir */ - mxman_wifi_kobject_ref_put(); -} - -void slsi_purge_scan_results_locked(struct netdev_vif *ndev_vif, u16 scan_id) -{ - struct slsi_scan_result *scan_result; - struct slsi_scan_result *prev = NULL; - - scan_result = ndev_vif->scan[scan_id].scan_results; - while (scan_result) { - slsi_kfree_skb(scan_result->beacon); - slsi_kfree_skb(scan_result->probe_resp); - prev = scan_result; - scan_result = scan_result->next; - kfree(prev); - } - ndev_vif->scan[scan_id].scan_results = NULL; -} - -void slsi_purge_scan_results(struct netdev_vif *ndev_vif, u16 scan_id) -{ - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - slsi_purge_scan_results_locked(ndev_vif, scan_id); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); -} - -struct sk_buff *slsi_dequeue_cached_scan_result(struct slsi_scan *scan, int *count) -{ - struct sk_buff *skb = NULL; - struct slsi_scan_result *scan_result = scan->scan_results; - - if (scan_result) { - if (scan_result->beacon) { - skb = scan_result->beacon; - scan_result->beacon = NULL; - } else if (scan_result->probe_resp) { - skb = scan_result->probe_resp; - scan_result->probe_resp = NULL; - } else { - SLSI_ERR_NODEV("Scan entry with no beacon /probe resp!!\n"); - } - - /*If beacon and probe response indicated above , remove the entry*/ - if (!scan_result->beacon && !scan_result->probe_resp) { - scan->scan_results = scan_result->next; - kfree(scan_result); - if (count) - (*count)++; - } - } - return skb; -} - -void slsi_get_hw_mac_address(struct slsi_dev *sdev, u8 *addr) -{ -#ifndef SLSI_TEST_DEV - const struct firmware *e = NULL; - int i; - u32 u[ETH_ALEN]; - char path_name[MX_WLAN_FILE_PATH_LEN_MAX]; - int r; - bool valid = false; - - /* Module parameter override */ - r = sscanf(mac_addr_override, "%02X:%02X:%02X:%02X:%02X:%02X", &u[0], &u[1], &u[2], &u[3], &u[4], &u[5]); - if (r != ETH_ALEN) { - SLSI_ERR(sdev, "mac_addr modparam set, but format is incorrect (should be e.g. xx:xx:xx:xx:xx:xx)\n"); - goto mac_sysfs; - } - for (i = 0; i < ETH_ALEN; i++) { - if (u[i] != 0xff) - valid = true; - addr[i] = u[i] & 0xff; - } - - /* If the override is valid, use it */ - if (valid) { - SLSI_INFO(sdev, "MAC address from modparam: %02X:%02X:%02X:%02X:%02X:%02X\n", - u[0], u[1], u[2], u[3], u[4], u[5]); - return; - } - - /* Sysfs parameter override */ -mac_sysfs: - r = sscanf(sysfs_mac_override, "%02X:%02X:%02X:%02X:%02X:%02X", &u[0], &u[1], &u[2], &u[3], &u[4], &u[5]); - if (r != ETH_ALEN) { - SLSI_ERR(sdev, "mac_addr in sysfs set, but format is incorrect (should be e.g. xx:xx:xx:xx:xx:xx)\n"); - goto mac_file; - } - for (i = 0; i < ETH_ALEN; i++) { - if (u[i] != 0xff) - valid = true; - addr[i] = u[i] & 0xff; - } - - /* If the override is valid, use it */ - if (valid) { - SLSI_INFO(sdev, "MAC address from sysfs: %02X:%02X:%02X:%02X:%02X:%02X\n", - u[0], u[1], u[2], u[3], u[4], u[5]); - return; - } - - /* read mac.txt */ -mac_file: - if (sdev->maddr_file_name) { - scnprintf(path_name, MX_WLAN_FILE_PATH_LEN_MAX, "wlan/%s", sdev->maddr_file_name); - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "MAC address file : %s\n", path_name); - - r = mx140_file_request_device_conf(sdev->maxwell_core, &e, path_name); - if (r != 0) - goto mac_efs; - - if (!e) { - SLSI_ERR(sdev, "mx140_file_request_device_conf() returned succes, but firmware was null\n"); - goto mac_efs; - } - r = sscanf(e->data, "%02X:%02X:%02X:%02X:%02X:%02X", &u[0], &u[1], &u[2], &u[3], &u[4], &u[5]); - mx140_file_release_conf(sdev->maxwell_core, e); - if (r != ETH_ALEN) { - SLSI_ERR(sdev, "%s exists, but format is incorrect (should be e.g. xx:xx:xx:xx:xx:xx)\n", path_name); - goto mac_efs; - } - for (i = 0; i < ETH_ALEN; i++) - addr[i] = u[i] & 0xff; - SLSI_INFO(sdev, "MAC address loaded from %s: %02X:%02X:%02X:%02X:%02X:%02X\n", path_name, u[0], u[1], u[2], u[3], u[4], u[5]); - return; - } -mac_efs: -#ifdef CONFIG_SCSC_WLAN_MAC_ADDRESS_FILENAME - r = mx140_request_file(sdev->maxwell_core, CONFIG_SCSC_WLAN_MAC_ADDRESS_FILENAME, &e); - if (r != 0) - goto mac_default; - if (!e) { - SLSI_ERR(sdev, "mx140_request_file() returned succes, but firmware was null\n"); - goto mac_default; - } - r = sscanf(e->data, "%02X:%02X:%02X:%02X:%02X:%02X", &u[0], &u[1], &u[2], &u[3], &u[4], &u[5]); - if (r != ETH_ALEN) { - SLSI_ERR(sdev, "%s exists, but format is incorrect (%d) [%20s] (should be e.g. xx:xx:xx:xx:xx:xx)\n", - CONFIG_SCSC_WLAN_MAC_ADDRESS_FILENAME, r, e->data); - goto mac_default; - } - for (i = 0; i < ETH_ALEN; i++) { - if (u[i] != 0xff) - valid = true; - addr[i] = u[i] & 0xff; - } -#endif - /* If MAC address seems valid, finished */ - if (valid) { - SLSI_INFO(sdev, "MAC address loaded from %s: %02X:%02X:%02X:%02X:%02X:%02X\n", - CONFIG_SCSC_WLAN_MAC_ADDRESS_FILENAME, u[0], u[1], u[2], u[3], u[4], u[5]); - - /* MAC address read could hold invalid values, try to fix it to normal address */ - if (addr[0] & 0x01) { - addr[0] = addr[0] & 0xfe; - SLSI_INFO(sdev, "MAC address invalid, fixed address: %pM\n", addr); - } - mx140_release_file(sdev->maxwell_core, e); - return; - } -mac_default: - /* This is safe to call, even if the struct firmware handle is NULL */ - mx140_file_release_conf(sdev->maxwell_core, e); - - SLSI_ETHER_COPY(addr, SLSI_DEFAULT_HW_MAC_ADDR); -#ifdef CONFIG_ARCH_EXYNOS - /* Randomise MAC address from the soc uid */ - addr[3] = (exynos_soc_info.unique_id & 0xFF0000000000) >> 40; - addr[4] = (exynos_soc_info.unique_id & 0x00FF00000000) >> 32; - addr[5] = (exynos_soc_info.unique_id & 0x0000FF000000) >> 24; -#endif - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, - "MAC addr file NOT found, using default MAC ADDR: %pM\n", addr); -#else - /* We use FIXED Mac addresses with the unittest driver */ - struct slsi_test_dev *uftestdev = (struct slsi_test_dev *)sdev->maxwell_core; - - SLSI_ETHER_COPY(addr, uftestdev->hw_addr); - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "Test Device Address: %pM\n", addr); -#endif -} - -static void write_wifi_version_info_file(struct slsi_dev *sdev) -{ -#if defined(ANDROID_VERSION) && (ANDROID_VERSION >= 90000) - char *filepath = "/data/vendor/conn/.wifiver.info"; -#else - char *filepath = "/data/misc/conn/.wifiver.info"; -#endif - char buf[256]; - char build_id_fw[128]; - char build_id_drv[64]; - -#ifndef CONFIG_SCSC_WLBTD - struct file *fp = NULL; - - fp = filp_open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0644); - - if (IS_ERR(fp)) { - SLSI_WARN(sdev, "version file wasn't found\n"); - return; - } else if (!fp) { - SLSI_WARN(sdev, "%s doesn't exist.\n", filepath); - return; - } -#endif - mxman_get_fw_version(build_id_fw, 128); - mxman_get_driver_version(build_id_drv, 64); - - /* WARNING: - * Please do not change the format of the following string - * as it can have fatal consequences. - * The framework parser for the version may depend on this - * exact formatting. - * - * Also beware that ANDROID_VERSION will not be defined in AOSP. - */ -#if defined(ANDROID_VERSION) && (ANDROID_VERSION >= 90000) - /* P-OS */ - snprintf(buf, sizeof(buf), - "%s\n" /* drv_ver: already appended by mxman_get_driver_version() */ - "f/w_ver: %s\n" - "hcf_ver_hw: %s\n" - "hcf_ver_sw: %s\n" - "regDom_ver: %d.%d\n", - build_id_drv, - build_id_fw, - sdev->mib[0].platform, - sdev->mib[1].platform, - ((sdev->reg_dom_version >> 8) & 0xFF), (sdev->reg_dom_version & 0xFF)); -#else - /* O-OS, or unknown */ - snprintf(buf, sizeof(buf), - "%s (f/w_ver: %s)\nregDom_ver: %d.%d\n", - build_id_drv, - build_id_fw, - ((sdev->reg_dom_version >> 8) & 0xFF), (sdev->reg_dom_version & 0xFF)); -#endif - -/* If ANDROID_VERSION is not known, avoid writing the file, as it could go to the wrong - * location. - */ -#ifdef ANDROID_VERSION -#ifdef CONFIG_SCSC_WLBTD - wlbtd_write_file(filepath, buf); -#else - kernel_write(fp, buf, strlen(buf), 0); - if (fp) - filp_close(fp, NULL); -#endif - - SLSI_INFO(sdev, "Succeed to write firmware/host information to .wifiver.info\n"); -#else - SLSI_UNUSED_PARAMETER(filepath); -#endif -} - -static void write_m_test_chip_version_file(struct slsi_dev *sdev) -{ -#ifdef CONFIG_SCSC_WLBTD - char *filepath = "/data/vendor/conn/.cid.info"; - char buf[256]; - - snprintf(buf, sizeof(buf), "%s\n", SCSC_RELEASE_SOLUTION); - - wlbtd_write_file(filepath, buf); - - SLSI_WARN(sdev, "Wrote chip information to .cid.info\n"); -#endif -} - - -#ifdef CONFIG_SCSC_WLAN_DEBUG -int slsi_start_monitor_mode(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u8 device_address[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - ndev_vif->vif_type = FAPI_VIFTYPE_MONITOR; - - if (slsi_mlme_add_vif(sdev, dev, dev->dev_addr, device_address) != 0) { - SLSI_NET_ERR(dev, "add VIF for Monitor mode failed\n"); - ndev_vif->vif_type = SLSI_VIFTYPE_UNSPECIFIED; - return -EINVAL; - } - - /* set the link type for the device; it depends on the format of - * packet the firmware is going to Pass to Host. - * - * If the firmware passes MA data in 802.11 frame format, then - * dev->type = ARPHRD_IEEE80211; - * - * If the firmware adds Radio TAP header to MA data, - * dev->type = ARPHRD_IEEE80211_RADIOTAP; - */ - dev->type = ARPHRD_IEEE80211_RADIOTAP; - ndev_vif->activated = true; - return 0; -} - -void slsi_stop_monitor_mode(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "de-activate monitor VIF\n"); - slsi_mlme_del_vif(sdev, dev); - slsi_vif_deactivated(sdev, dev); -} -#endif - -#ifdef CONFIG_SCSC_LOG_COLLECTION -static int slsi_hcf_collect(struct scsc_log_collector_client *collect_client, size_t size) -{ - struct slsi_dev *sdev = (struct slsi_dev *)collect_client->prv; - int ret = 0; - u8 index = sdev->collect_mib.num_files; - u8 i; - u8 *data; - - SLSI_INFO_NODEV("Collecting WLAN HCF\n"); - - if (!sdev->collect_mib.enabled) - SLSI_INFO_NODEV("Collection not enabled\n"); - - spin_lock(&sdev->collect_mib.in_collection); - ret = scsc_log_collector_write(&index, sizeof(char), 1); - if (ret) { - spin_unlock(&sdev->collect_mib.in_collection); - return ret; - } - - for (i = 0; i < index; i++) { - SLSI_INFO_NODEV("Collecting WLAN HCF. File %s\n", sdev->collect_mib.file[i].file_name); - /* Write file name */ - ret = scsc_log_collector_write((char *)&sdev->collect_mib.file[i].file_name, 32, 1); - if (ret) { - spin_unlock(&sdev->collect_mib.in_collection); - return ret; - } - /* Write file len */ - ret = scsc_log_collector_write((char *)&sdev->collect_mib.file[i].len, sizeof(u16), 1); - if (ret) { - spin_unlock(&sdev->collect_mib.in_collection); - return ret; - } - /* Write data */ - data = sdev->collect_mib.file[i].data; - if (!data) - continue; - ret = scsc_log_collector_write((char *)data, sdev->collect_mib.file[i].len, 1); - if (ret) { - spin_unlock(&sdev->collect_mib.in_collection); - return ret; - } - } - spin_unlock(&sdev->collect_mib.in_collection); - - return ret; -} - -/* Collect client registration for HCF file*/ -struct scsc_log_collector_client slsi_hcf_client = { - .name = "wlan_hcf", - .type = SCSC_LOG_CHUNK_WLAN_HCF, - .collect_init = NULL, - .collect = slsi_hcf_collect, - .collect_end = NULL, - .prv = NULL, -}; -#endif - -int slsi_start(struct slsi_dev *sdev) -{ -#ifndef CONFIG_SCSC_DOWNLOAD_FILE - const struct firmware *fw = NULL; -#endif - int err = 0, r; - int i; - char alpha2[3]; -#ifdef CONFIG_SCSC_WLAN_AP_INFO_FILE - u32 offset = 0; - struct file *fp = NULL; -#if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000 - char *filepath = "/data/vendor/conn/.softap.info"; -#else - char *filepath = "/data/misc/conn/.softap.info"; -#endif - char buf[512]; -#endif -#ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA - struct file *file_ptr = NULL; - char *ant_file_path = "/data/vendor/conn/.ant.info"; - char ant_mode = '0'; - u16 antenna = 0; -#endif - - if (WARN_ON(!sdev)) - return -EINVAL; - - SLSI_MUTEX_LOCK(sdev->start_stop_mutex); - - slsi_wakelock(&sdev->wlan_wl); - - if (sdev->device_state != SLSI_DEVICE_STATE_STOPPED) { - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "Device already started: device_state:%d\n", sdev->device_state); - goto done; - } - - if (sdev->recovery_status) { - r = wait_for_completion_timeout(&sdev->recovery_completed, - msecs_to_jiffies(sdev->recovery_timeout)); - if (r == 0) - SLSI_INFO(sdev, "recovery_completed timeout\n"); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) - reinit_completion(&sdev->recovery_completed); -#else - /*This is how the macro is used in the older version.*/ - INIT_COMPLETION(sdev->recovery_completed); -#endif - } - - sdev->device_state = SLSI_DEVICE_STATE_STARTING; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) - reinit_completion(&sdev->sig_wait.completion); -#else - INIT_COMPLETION(sdev->sig_wait.completion); -#endif - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Step [1/2]: Start WLAN service\n"); - SLSI_EC_GOTO(slsi_sm_wlan_service_open(sdev), err, err_done); - /** - * Download MIB data, if any. - */ - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Step [2/3]: Send MIB configuration\n"); - - sdev->local_mib.mib_hash = 0; /* Reset localmib hash value */ -#ifndef SLSI_TEST_DEV -#ifdef CONFIG_SCSC_LOG_COLLECTION - spin_lock_init(&sdev->collect_mib.in_collection); - sdev->collect_mib.num_files = 0; - sdev->collect_mib.enabled = false; -#endif -#ifndef CONFIG_SCSC_DOWNLOAD_FILE - /* The "_t" HCF is used in RF Test mode and wlanlite/production test mode */ - if (slsi_is_rf_test_mode_enabled() || slsi_is_test_mode_enabled()) { - sdev->mib[0].mib_file_name = mib_file_t; - sdev->mib[1].mib_file_name = mib_file2_t; - } else { - sdev->mib[0].mib_file_name = slsi_mib_file; - sdev->mib[1].mib_file_name = slsi_mib_file2; - } - - /* Place MIB files in shared memory */ - for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++) { - err = slsi_mib_open_file(sdev, &sdev->mib[i], &fw); - - /* Only the first file is mandatory */ - if (i == 0 && err) { - SLSI_ERR(sdev, "mib: Mandatory wlan hcf missing. WLAN will not start (err=%d)\n", err); - slsi_sm_wlan_service_close(sdev); - goto err_done; - } - } - - err = slsi_sm_wlan_service_start(sdev); - if (err) { - SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err); - slsi_mib_close_file(sdev, fw); - slsi_sm_wlan_service_close(sdev); - goto err_done; - } - slsi_mib_close_file(sdev, fw); -#else - /* Download main MIB file via mlme_set */ - err = slsi_sm_wlan_service_start(sdev); - if (err) { - SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err); - slsi_sm_wlan_service_close(sdev); - goto err_done; - } - SLSI_EC_GOTO(slsi_mib_download_file(sdev, &sdev->mib), err, err_hip_started); -#endif - /* Always try to download optional localmib file via mlme_set, ignore error */ - (void)slsi_mib_download_file(sdev, &sdev->local_mib); -#endif - /** - * Download MIB data, if any. - * Get f/w capabilities and default configuration - * configure firmware - */ - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - sdev->device_config.rssi_boost_2g = 0; - sdev->device_config.rssi_boost_5g = 0; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Step [3/3]: Get MIB configuration\n"); - SLSI_EC_GOTO(slsi_mib_initial_get(sdev), err, err_hip_started); - SLSI_INFO(sdev, "=== Version info from the [MIB] ===\n"); - SLSI_INFO(sdev, "HW Version : 0x%.4X (%u)\n", sdev->chip_info_mib.chip_version, sdev->chip_info_mib.chip_version); - SLSI_INFO(sdev, "Platform : 0x%.4X (%u)\n", sdev->plat_info_mib.plat_build, sdev->plat_info_mib.plat_build); - slsi_cfg80211_update_wiphy(sdev); - - /* Get UnifiCountryList */ - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - sdev->device_config.host_state = SLSI_HOSTSTATE_CELLULAR_ACTIVE; - err = slsi_read_unifi_countrylist(sdev, SLSI_PSID_UNIFI_COUNTRY_LIST); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - if (err) - goto err_hip_started; - - /* Get unifiDefaultCountry */ - err = slsi_read_default_country(sdev, alpha2, 1); - alpha2[2] = '\0'; - if (err < 0) - goto err_hip_started; - - /* unifiDefaultCountry != world_domain */ - if (!(alpha2[0] == '0' && alpha2[1] == '0')) - if (memcmp(sdev->device_config.domain_info.regdomain->alpha2, alpha2, 2) != 0) { - memcpy(sdev->device_config.domain_info.regdomain->alpha2, alpha2, 2); - - /* Read the regulatory params for the country*/ - if (slsi_read_regulatory_rules(sdev, &sdev->device_config.domain_info, alpha2) == 0) { - slsi_reset_channel_flags(sdev); - wiphy_apply_custom_regulatory(sdev->wiphy, sdev->device_config.domain_info.regdomain); - } - } - /* Do nothing for unifiDefaultCountry == world_domain */ - - /* write .wifiver.info */ - write_wifi_version_info_file(sdev); - - /* write .cid.info */ - write_m_test_chip_version_file(sdev); - -#ifdef CONFIG_SCSC_WLAN_AP_INFO_FILE - /* writing .softap.info in /data/vendor/conn */ - fp = filp_open(filepath, O_WRONLY | O_CREAT, 0644); - - if (!fp) { - WARN(1, "%s doesn't exist\n", filepath); - } else if (IS_ERR(fp)) { - WARN(1, "%s open returned error %d\n", filepath, IS_ERR(fp)); - } else { - offset = snprintf(buf + offset, sizeof(buf), "#softap.info\n"); - offset += snprintf(buf + offset, sizeof(buf), "DualBandConcurrency=%s\n", sdev->dualband_concurrency ? "yes" : "no"); - offset += snprintf(buf + offset, sizeof(buf), "DualInterface=%s\n", "yes"); - offset += snprintf(buf + offset, sizeof(buf), "5G=%s\n", sdev->band_5g_supported ? "yes" : "no"); - offset += snprintf(buf + offset, sizeof(buf), "maxClient=%d\n", !sdev->softap_max_client ? SLSI_MIB_MAX_CLIENT : sdev->softap_max_client); - - /* following are always supported */ - offset += snprintf(buf + offset, sizeof(buf), "HalFn_setCountryCodeHal=yes\n"); - offset += snprintf(buf + offset, sizeof(buf), "HalFn_getValidChannels=yes\n"); -#ifdef CONFIG_SCSC_WLBTD - wlbtd_write_file(filepath, buf); -#else - - kernel_write(fp, buf, strlen(buf), 0); -#endif - if (fp) - filp_close(fp, NULL); - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Succeed to write softap information to .softap.info\n"); - } -#endif - -#ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA - if (slsi_is_rf_test_mode_enabled()) { - /* reading antenna mode from /data/vendor/conn/.ant.info */ - file_ptr = filp_open(ant_file_path, O_RDONLY, 0); - /* if file is not found, set the default antenna value to 3(ANT_ALL) */ - if (!file_ptr) { - SLSI_DBG1(sdev, SLSI_CFG80211, "%s doesn't exist\n", ant_file_path); - slsi_set_mib_preferred_antenna(sdev, 3); - } else if (IS_ERR(file_ptr)) { - SLSI_DBG1(sdev, SLSI_CFG80211, "%s open returned error %d\n", ant_file_path, IS_ERR(file_ptr)); - slsi_set_mib_preferred_antenna(sdev, 3); - } else { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - kernel_read(file_ptr, &ant_mode, 1, &file_ptr->f_pos); -#else - kernel_read(file_ptr, file_ptr->f_pos, &ant_mode, 1); -#endif - antenna = ant_mode - '0'; - filp_close(file_ptr, NULL); - - slsi_set_mib_preferred_antenna(sdev, antenna); - } - } -#endif - -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Register with log collector to collect wlan hcf file */ - slsi_hcf_client.prv = sdev; - scsc_log_collector_register_client(&slsi_hcf_client); - sdev->collect_mib.enabled = true; -#endif - slsi_update_supported_channels_regd_flags(sdev); - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "---Driver started successfully---\n"); - sdev->device_state = SLSI_DEVICE_STATE_STARTED; - memset(sdev->rtt_vif, -1, sizeof(sdev->rtt_vif)); - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); - - slsi_kic_system_event(slsi_kic_system_event_category_initialisation, - slsi_kic_system_events_wifi_service_driver_started, GFP_KERNEL); - - slsi_wakeunlock(&sdev->wlan_wl); - return err; - -err_hip_started: -#ifndef SLSI_TEST_DEV - slsi_sm_wlan_service_stop(sdev); - slsi_hip_stop(sdev); - slsi_sm_wlan_service_close(sdev); -#endif - -err_done: - sdev->device_state = SLSI_DEVICE_STATE_STOPPED; - -done: - slsi_wakeunlock(&sdev->wlan_wl); - - slsi_kic_system_event(slsi_kic_system_event_category_initialisation, - slsi_kic_system_events_wifi_on, GFP_KERNEL); - - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); - return err; -} - -struct net_device *slsi_dynamic_interface_create(struct wiphy *wiphy, - const char *name, - enum nl80211_iftype type, - struct vif_params *params) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = NULL; - struct netdev_vif *ndev_vif = NULL; - int err = -EINVAL; - int iface; - - SLSI_DBG1(sdev, SLSI_CFG80211, "name:%s\n", name); - - iface = slsi_netif_dynamic_iface_add(sdev, name); - if (iface < 0) - return NULL; - - dev = slsi_get_netdev(sdev, iface); - if (!dev) - return NULL; - - ndev_vif = netdev_priv(dev); - - err = slsi_netif_register_rtlnl_locked(sdev, dev); - if (err) - return NULL; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - ndev_vif->iftype = type; - dev->ieee80211_ptr->iftype = type; - if (params) - dev->ieee80211_ptr->use_4addr = params->use_4addr; - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - return dev; -} - -static void slsi_stop_chip(struct slsi_dev *sdev) -{ -#ifdef CONFIG_SCSC_LOG_COLLECTION - u8 index = sdev->collect_mib.num_files; - u8 i; -#endif - WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->start_stop_mutex)); - - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "netdev_up_count:%d device_state:%d\n", sdev->netdev_up_count, sdev->device_state); - - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) - return; - - /* Only shutdown on the last device going down. */ - if (sdev->netdev_up_count) - return; - - complete_all(&sdev->sig_wait.completion); - -#ifdef CONFIG_SCSC_LOG_COLLECTION - sdev->collect_mib.enabled = false; - scsc_log_collector_unregister_client(&slsi_hcf_client); - for (i = 0; i < index; i++) - kfree(sdev->collect_mib.file[i].data); -#endif - - slsi_reset_channel_flags(sdev); - slsi_regd_init(sdev); - sdev->device_state = SLSI_DEVICE_STATE_STOPPING; - - slsi_sm_wlan_service_stop(sdev); - sdev->device_state = SLSI_DEVICE_STATE_STOPPED; - - slsi_hip_stop(sdev); -#ifndef SLSI_TEST_DEV - slsi_sm_wlan_service_close(sdev); -#endif - slsi_kic_system_event(slsi_kic_system_event_category_deinitialisation, - slsi_kic_system_events_wifi_service_driver_stopped, GFP_KERNEL); - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - sdev->mlme_blocked = false; - - slsi_kic_system_event(slsi_kic_system_event_category_deinitialisation, - slsi_kic_system_events_wifi_off, GFP_KERNEL); - - slsi_dbg_track_skb_report(); - slsi_dbg_track_skb_reset(); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); -} - -void slsi_vif_cleanup(struct slsi_dev *sdev, struct net_device *dev, bool hw_available) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int i; - - SLSI_NET_DBG3(dev, SLSI_INIT_DEINIT, "clean VIF\n"); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (ndev_vif->activated) { - netif_carrier_off(dev); - for (i = 0; i < SLSI_ADHOC_PEER_CONNECTIONS_MAX; i++) { - struct slsi_peer *peer = ndev_vif->peer_sta_record[i]; - - if (peer && peer->valid) - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - } - - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - bool already_disconnected = false; - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Station active: hw_available=%d\n", hw_available); - if (hw_available) { - if (ndev_vif->sta.sta_bss) { - slsi_mlme_disconnect(sdev, dev, ndev_vif->sta.sta_bss->bssid, FAPI_REASONCODE_UNSPECIFIED_REASON, true); - slsi_handle_disconnect(sdev, dev, ndev_vif->sta.sta_bss->bssid, 0, NULL, 0); - already_disconnected = true; - } else { - slsi_mlme_del_vif(sdev, dev); - } - } - if (!already_disconnected) { - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Calling slsi_vif_deactivated\n"); - slsi_vif_deactivated(sdev, dev); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) - cfg80211_disconnected(dev, FAPI_REASONCODE_UNSPECIFIED_REASON, NULL, 0, false, GFP_ATOMIC); -#else - cfg80211_disconnected(dev, FAPI_REASONCODE_UNSPECIFIED_REASON, NULL, 0, GFP_ATOMIC); -#endif - } - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) { - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "AP active\n"); - if (hw_available) { - struct slsi_peer *peer; - int j = 0; - - while (j < SLSI_PEER_INDEX_MAX) { - peer = ndev_vif->peer_sta_record[j]; - if (peer && peer->valid) - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - ++j; - } - slsi_mlme_del_vif(sdev, dev); - } - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Calling slsi_vif_deactivated\n"); - slsi_vif_deactivated(sdev, dev); - - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO) - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_NO_VIF); - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_UNSYNCHRONISED) { - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - slsi_wlan_unsync_vif_deactivate(sdev, dev, hw_available); - } else { - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "P2P active - Deactivate\n"); - slsi_p2p_vif_deactivate(sdev, dev, hw_available); - } - } -#ifdef CONFIG_SCSC_WLAN_DEBUG - else if (ndev_vif->vif_type == FAPI_VIFTYPE_MONITOR) - slsi_stop_monitor_mode(sdev, dev); -#endif - } -} - -void slsi_scan_cleanup(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int i; - struct cfg80211_scan_info info = {.aborted = false}; - - SLSI_NET_DBG3(dev, SLSI_INIT_DEINIT, "clean scan_data\n"); - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - for (i = 0; i < SLSI_SCAN_MAX; i++) { - if ((ndev_vif->scan[i].scan_req || ndev_vif->scan[i].acs_request) && - !sdev->mlme_blocked) - slsi_mlme_del_scan(sdev, dev, (ndev_vif->ifnum << 8 | i), false); - slsi_purge_scan_results(ndev_vif, i); - if (ndev_vif->scan[i].scan_req && i == SLSI_SCAN_HW_ID) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - cfg80211_scan_done(ndev_vif->scan[i].scan_req, &info); -#else - cfg80211_scan_done(ndev_vif->scan[i].scan_req, false); -#endif - - if (ndev_vif->scan[i].sched_req && i == SLSI_SCAN_SCHED_ID) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) - cfg80211_sched_scan_stopped(sdev->wiphy, ndev_vif->scan[i].sched_req->reqid); -#else - cfg80211_sched_scan_stopped(sdev->wiphy); -#endif - - ndev_vif->scan[i].scan_req = NULL; - kfree(ndev_vif->scan[i].acs_request); - ndev_vif->scan[i].acs_request = NULL; - ndev_vif->scan[i].sched_req = NULL; - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); -} - -static void slsi_stop_net_dev_locked(struct slsi_dev *sdev, struct net_device *dev, bool hw_available) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "Stopping netdev_up_count=%d, hw_available = %d\n", sdev->netdev_up_count, hw_available); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->start_stop_mutex)); - - if (!ndev_vif->is_available) { - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "Not Available\n"); - return; - } - - if (WARN_ON(!sdev->netdev_up_count)) { - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "sdev->netdev_up_count=%d\n", sdev->netdev_up_count); - return; - } - - complete_all(&ndev_vif->sig_wait.completion); - - slsi_scan_cleanup(sdev, dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - slsi_vif_cleanup(sdev, dev, hw_available); - ndev_vif->is_available = false; - sdev->netdev_up_count--; - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - slsi_stop_chip(sdev); -} - -/* Called when a net device wants to go DOWN */ -void slsi_stop_net_dev(struct slsi_dev *sdev, struct net_device *dev) -{ - SLSI_MUTEX_LOCK(sdev->start_stop_mutex); - slsi_stop_net_dev_locked(sdev, dev, sdev->recovery_status ? false : true); - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); -} - -/* Called when we get sdio_removed */ -void slsi_stop(struct slsi_dev *sdev) -{ - struct net_device *dev; - int i; - - SLSI_MUTEX_LOCK(sdev->start_stop_mutex); - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "netdev_up_count:%d\n", sdev->netdev_up_count); - - complete_all(&sdev->sig_wait.completion); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) { - dev = slsi_get_netdev_locked(sdev, i); - if (dev) - slsi_stop_net_dev_locked(sdev, sdev->netdev[i], false); - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex); -} - -/* MIB download handling */ -static u8 *slsi_mib_slice(struct slsi_dev *sdev, const u8 *data, u32 length, u32 *p_parsed_len, - u32 *p_mib_slice_len) -{ - const u8 *p = data; - u8 *mib_slice; - u32 mib_slice_len = 0; - - SLSI_UNUSED_PARAMETER(sdev); - - if (!length) - return NULL; - - mib_slice = kmalloc(length + 4, GFP_KERNEL); - if (!mib_slice) - return NULL; - - while (length >= 4) { - u16 psid = SLSI_BUFF_LE_TO_U16(p); - u16 pslen = (u16)(4 + SLSI_BUFF_LE_TO_U16(&p[2])); - - if (pslen & 0x1) - pslen++; - - if (psid & CSR_WIFI_SME_MIB2_HOST_PSID_MASK) { - /* do nothing */ - } else { - /* SLSI_ERR (sdev, "PSID=0x%04X : FW\n", psid); */ -#define CSR_WIFI_HOSTIO_MIB_SET_MAX (1800) - if ((mib_slice_len + pslen) > CSR_WIFI_HOSTIO_MIB_SET_MAX) - break; - if (pslen > length + 4) { - SLSI_ERR(sdev, "length %u read from MIB file > space %u - corrupt file?\n", pslen, length + 4); - mib_slice_len = 0; - break; - } - memcpy(&mib_slice[mib_slice_len], p, pslen); - mib_slice_len += pslen; - } - p += pslen; - length -= pslen; - } - - *p_mib_slice_len = mib_slice_len; - *p_parsed_len = (p - data); - - return mib_slice; -} - -/* Extract the platform name string from the HCF file */ -static int slsi_mib_get_platform(struct slsi_dev_mib_info *mib_info) -{ - size_t plat_name_len; - int pos = 0; - - /* The mib_data passed to this function should already - * have had its HCF header skipped. - * - * This is shoehorned into specific PSIDs to allow backward - * compatibility, so we must look into the HCF payload - * instead of the header :( - * - * The updated configcmd util guarantees that these keys - * will appear first: - * - * PSIDs: - * 0xfffe - 16 bit version ID, value 1. - * 0xffff - If version ID=1, holds platform name string. - */ - - mib_info->platform[0] = '\0'; - - /* Sanity - payload long enough for info? */ - if (mib_info->mib_len < 12) { - SLSI_INFO_NODEV("HCF file too short\n"); - return -EINVAL; /* file too short */ - } - - if (mib_info->mib_data[pos++] != 0xFE || /* Version ID FFFE */ - mib_info->mib_data[pos++] != 0xFF) { - SLSI_INFO_NODEV("No HCF version ID\n"); - return -EINVAL; /* No version ID */ - } - if (mib_info->mib_data[pos++] != 0x01 || /* Len 1, LE */ - mib_info->mib_data[pos++] != 0x00) { - SLSI_INFO_NODEV("Bad length\n"); - return -EINVAL; /* Unknown length */ - } - if (mib_info->mib_data[pos++] != 0x01 || /* Header ID 1, LE */ - mib_info->mib_data[pos++] != 0x00) { - SLSI_INFO_NODEV("Bad version ID\n"); - return -EINVAL; /* Unknown version ID */ - } - if (mib_info->mib_data[pos++] != 0xFF || /* Platform Name FFFF */ - mib_info->mib_data[pos++] != 0xFF) { - SLSI_INFO_NODEV("No HCF platform name\n"); - return -EINVAL; /* No platform name */ - } - - /* Length of platform name */ - plat_name_len = mib_info->mib_data[pos++]; - plat_name_len |= (mib_info->mib_data[pos++] << 16); - - /* Sanity check */ - if (plat_name_len + pos > mib_info->mib_len || plat_name_len < 2) { - SLSI_ERR_NODEV("Bad HCF FFFF key length %zu\n", - plat_name_len); - return -EINVAL; /* Implausible length */ - } - - /* Skip vldata header SC-506179-SP. This conveys the - * length of the platform string and is 2 or 3 octets long - * depending on the length of the string. - */ - { -#define SLSI_VLDATA_STRING 0xA0 -#define SLSI_VLDATA_LEN 0x17 - - u8 vlen_hdr = mib_info->mib_data[pos++]; - u8 vlen_len = vlen_hdr & SLSI_VLDATA_LEN; /* size of length field */ - - /* Skip vlen header octet */ - plat_name_len--; - - SLSI_DBG1_NODEV(SLSI_INIT_DEINIT, "vlhdr 0x%x, len %u\n", vlen_hdr, vlen_len); - - /* Is it an octet string type? */ - if (!(vlen_hdr & SLSI_VLDATA_STRING)) { - SLSI_ERR_NODEV("No string vlen header 0x%x\n", vlen_hdr); - return -EINVAL; - } - - /* Handle 1 or 2 octet length field only */ - if (vlen_len > 2) { - SLSI_ERR_NODEV("Too long octet string header %u\n", vlen_len); - return -EINVAL; - } - - /* Skip over the string length field. - * Note we just use datalength anyway. - */ - pos += vlen_len; - plat_name_len -= vlen_len; - } - - /* Limit the platform name to space in driver and read */ - { - size_t trunc_len = plat_name_len; - - if (trunc_len >= sizeof(mib_info->platform)) - trunc_len = sizeof(mib_info->platform) - 1; - - /* Extract platform name */ - memcpy(mib_info->platform, &mib_info->mib_data[pos], trunc_len); - mib_info->platform[trunc_len] = '\0'; - - /* Print non-truncated string in log now */ - SLSI_INFO_NODEV("MIB platform: %.*s\n", (int)plat_name_len, &mib_info->mib_data[pos]); - - SLSI_DBG1_NODEV(SLSI_INIT_DEINIT, "plat_name_len: %zu + %u\n", - plat_name_len, (plat_name_len & 1)); - } - - /* Pad string to 16-bit boundary */ - plat_name_len += (plat_name_len & 1); - pos += plat_name_len; - - /* Advance over the keys we read, FW doesn't need them */ - mib_info->mib_data += pos; - mib_info->mib_len -= pos; - - SLSI_DBG1_NODEV(SLSI_INIT_DEINIT, "Skip %d octets HCF payload\n", pos); - - return 0; -} - -#define MGT_HASH_SIZE_BYTES 2 /* Hash will be contained in a uint32 */ -#define MGT_HASH_OFFSET 4 -static int slsi_mib_open_file(struct slsi_dev *sdev, struct slsi_dev_mib_info *mib_info, const struct firmware **fw) -{ - int r = -1; - const struct firmware *e = NULL; - const char *mib_file_ext; - char path_name[MX_WLAN_FILE_PATH_LEN_MAX]; - char *mib_file_name = mib_info->mib_file_name; -#ifdef CONFIG_SCSC_LOG_COLLECTION - u8 index = sdev->collect_mib.num_files; - u8 *data; -#endif - - if (!mib_file_name || !fw) - return -EINVAL; - - mib_info->mib_data = NULL; - mib_info->mib_len = 0; - mib_info->mib_hash = 0; /* Reset mib hash value */ - - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "MIB file - Name : %s\n", mib_file_name); - - /* Use MIB file compatibility mode? */ - mib_file_ext = strrchr(mib_file_name, '.'); - if (!mib_file_ext) { - SLSI_ERR(sdev, "configuration file name '%s' invalid\n", mib_file_name); - return -EINVAL; - } - - /* Build MIB file path from override */ - scnprintf(path_name, MX_WLAN_FILE_PATH_LEN_MAX, "wlan/%s", mib_file_name); - SLSI_INFO(sdev, "Path to the MIB file : %s\n", path_name); - - r = mx140_file_request_conf(sdev->maxwell_core, &e, "wlan", mib_file_name); - if (r || (!e)) { - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "Skip MIB download as file %s is NOT found\n", mib_file_name); - *fw = e; - return r; - } - - mib_info->mib_data = (u8 *)e->data; - mib_info->mib_len = e->size; - -#ifdef CONFIG_SCSC_LOG_COLLECTION - spin_lock(&sdev->collect_mib.in_collection); - memset(&sdev->collect_mib.file[index].file_name, 0, 32); - memcpy(&sdev->collect_mib.file[index].file_name, mib_file_name, 32); - sdev->collect_mib.file[index].len = mib_info->mib_len; - data = kmalloc(mib_info->mib_len, GFP_ATOMIC); - if (!data) { - spin_unlock(&sdev->collect_mib.in_collection); - goto cont; - } - memcpy(data, mib_info->mib_data, mib_info->mib_len); - sdev->collect_mib.file[index].data = data; - sdev->collect_mib.num_files += 1; - spin_unlock(&sdev->collect_mib.in_collection); -cont: -#endif - /* Check MIB file header */ - if (mib_info->mib_len >= 8 && /* Room for header */ - /*(sdev->mib_data[6] & 0xF0) == 0x20 && */ /* WLAN subsystem */ - mib_info->mib_data[7] == 1) { /* First file format */ - int i; - - mib_info->mib_hash = 0; - - for (i = 0; i < MGT_HASH_SIZE_BYTES; i++) - mib_info->mib_hash = (mib_info->mib_hash << 8) | mib_info->mib_data[i + MGT_HASH_OFFSET]; - - SLSI_INFO(sdev, "MIB hash: 0x%.04x\n", mib_info->mib_hash); - /* All good - skip header and continue */ - mib_info->mib_data += 8; - mib_info->mib_len -= 8; - - /* Extract platform name if available */ - slsi_mib_get_platform(mib_info); - } else { - /* Bad header */ - SLSI_ERR(sdev, "configuration file '%s' has bad header\n", mib_info->mib_file_name); - mx140_file_release_conf(sdev->maxwell_core, e); - return -EINVAL; - } - - *fw = e; - return 0; -} - -static int slsi_mib_close_file(struct slsi_dev *sdev, const struct firmware *e) -{ - SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "MIB close %p\n", e); - - if (!e || !sdev) - return -EIO; - - mx140_file_release_conf(sdev->maxwell_core, e); - - return 0; -} - -static int slsi_mib_download_file(struct slsi_dev *sdev, struct slsi_dev_mib_info *mib_info) -{ - int r = -1; - const struct firmware *e = NULL; - u8 *mib_slice; - u32 mib_slice_len, parsed_len; - - r = slsi_mib_open_file(sdev, mib_info, &e); - if (r) - return r; - /** - * MIB data should not be larger than CSR_WIFI_HOSTIO_MIB_SET_MAX. - * Slice it into smaller ones and download one by one - */ - while (mib_info->mib_len > 0) { - mib_slice = slsi_mib_slice(sdev, mib_info->mib_data, mib_info->mib_len, &parsed_len, &mib_slice_len); - if (!mib_slice) - break; - if (mib_slice_len == 0 || mib_slice_len > mib_info->mib_len) { - /* Sanity check MIB parsing */ - SLSI_ERR(sdev, "slsi_mib_slice returned implausible %d\n", mib_slice_len); - r = -EINVAL; - kfree(mib_slice); - break; - } - r = slsi_mlme_set(sdev, NULL, mib_slice, mib_slice_len); - kfree(mib_slice); - if (r != 0) /* some mib can fail to be set, but continue */ - SLSI_ERR(sdev, "mlme set failed r=0x%x during downloading:'%s'\n", - r, mib_info->mib_file_name); - - mib_info->mib_data += parsed_len; - mib_info->mib_len -= parsed_len; - } - - slsi_mib_close_file(sdev, e); - - return r; -} - -static int slsi_mib_initial_get(struct slsi_dev *sdev) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - int *band = sdev->supported_5g_channels; - int rx_len = 0; - int r; - int i = 0; - int j = 0; - int chan_start = 0; - int chan_count = 0; - int index = 0; - int mib_index = 0; - static const struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_CHIP_VERSION, { 0, 0 } }, - { SLSI_PSID_UNIFI_SUPPORTED_CHANNELS, { 0, 0 } }, - { SLSI_PSID_UNIFI_HT_ACTIVATED, {0, 0} }, - { SLSI_PSID_UNIFI_VHT_ACTIVATED, {0, 0} }, - { SLSI_PSID_UNIFI_HT_CAPABILITIES, {0, 0} }, - { SLSI_PSID_UNIFI_VHT_CAPABILITIES, {0, 0} }, - { SLSI_PSID_UNIFI_HARDWARE_PLATFORM, {0, 0} }, - { SLSI_PSID_UNIFI_REG_DOM_VERSION, {0, 0} }, - { SLSI_PSID_UNIFI_NAN_ENABLED, {0, 0} }, - { SLSI_PSID_UNIFI_DEFAULT_DWELL_TIME, {0, 0} }, -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - { SLSI_PSID_UNIFI_WI_FI_SHARING5_GHZ_CHANNEL, {0, 0} }, -#endif -#ifdef CONFIG_SCSC_WLAN_AP_INFO_FILE - { SLSI_PSID_UNIFI_DUAL_BAND_CONCURRENCY, {0, 0} }, - { SLSI_PSID_UNIFI_MAX_CLIENT, {0, 0} }, -#endif -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - { SLSI_PSID_UNIFI_MAC_ADDRESS_RANDOMISATION, {0, 0} }, -#endif - { SLSI_PSID_UNIFI_DEFAULT_COUNTRY_WITHOUT_CH12_CH13, {0, 0} }, -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - { SLSI_PSID_UNIFI_ARP_DETECT_ACTIVATED, {0, 0} }, -#endif - { SLSI_PSID_UNIFI_APF_ENABLED, {0, 0} }, - { SLSI_PSID_UNIFI_SOFT_AP40_MHZ_ON24G, {0, 0} } - };/*Check the mibrsp.dataLength when a new mib is added*/ - - r = slsi_mib_encode_get_list(&mibreq, sizeof(get_values) / sizeof(struct slsi_mib_get_entry), get_values); - if (r != SLSI_MIB_STATUS_SUCCESS) - return -ENOMEM; - - mibrsp.dataLength = 194; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, mibrsp.data, mibrsp.dataLength, &rx_len); - kfree(mibreq.data); - if (r == 0) { - struct slsi_mib_value *values; - - mibrsp.dataLength = (u32)rx_len; - - values = slsi_mib_decode_get_list(&mibrsp, sizeof(get_values) / sizeof(struct slsi_mib_get_entry), get_values); - - if (!values) { - kfree(mibrsp.data); - return -EINVAL; - } - - if (values[mib_index].type != SLSI_MIB_TYPE_NONE) { /* CHIP_VERSION */ - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT); - sdev->chip_info_mib.chip_version = values[mib_index].u.uintValue; - } - - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { /* SUPPORTED_CHANNELS */ - int k = 0; - int increment = 4; /* increment channel by 4 for 5G and by 1 for 2G */ - int buf_len = 150; /* 150 bytes for 14+25=39 channels and spaces between them */ - char *supported_channels_buffer = kmalloc(buf_len, GFP_KERNEL); - int buf_pos = 0; - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_OCTET); - if (values[mib_index].type == SLSI_MIB_TYPE_OCTET) { - sdev->band_5g_supported = 0; - memset(sdev->supported_2g_channels, 0, sizeof(sdev->supported_2g_channels)); - memset(sdev->supported_5g_channels, 0, sizeof(sdev->supported_5g_channels)); - for (i = 0; i < values[mib_index].u.octetValue.dataLength / 2; i++) { - /* If any 5GHz channel is supported, update band_5g_supported */ - if ((values[mib_index].u.octetValue.data[i * 2] > 14) && - (values[mib_index].u.octetValue.data[i * 2 + 1] > 0)) { - sdev->band_5g_supported = 1; - break; - } - } - for (i = 0; i < values[mib_index].u.octetValue.dataLength; i += 2) { - increment = 4; - k = 0; - chan_start = values[mib_index].u.octetValue.data[i]; - chan_count = values[mib_index].u.octetValue.data[i + 1]; - band = sdev->supported_5g_channels; - if (chan_start < 15) { - increment = 1; - index = chan_start - 1; - band = sdev->supported_2g_channels; - } else if (chan_start >= 36 && chan_start <= 48) { - index = (chan_start - 36) / 4; - } else if (chan_start >= 52 && chan_start <= 64) { - index = ((chan_start - 52) / 4) + 4; - } else if (chan_start >= 100 && chan_start <= 140) { - index = ((chan_start - 100) / 4) + 8; - } else if (chan_start >= 149 && chan_start <= 165) { - index = ((chan_start - 149) / 4) + 20; - } else { - continue; - } - - for (j = 0; j < chan_count; j++) { - band[index + j] = 1; - buf_pos += snprintf(supported_channels_buffer + buf_pos, - buf_len - buf_pos, "%d ", (chan_start + k)); - k = k + increment; - } - sdev->enabled_channel_count += chan_count; - } - } - SLSI_DBG1(sdev, SLSI_CFG80211, "Value for Supported Channels mib: %s\n", - supported_channels_buffer); - } - - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* HT enabled? */ - sdev->fw_ht_enabled = values[mib_index].u.boolValue; - else - SLSI_WARN(sdev, "Error reading HT enabled mib\n"); - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* VHT enabled? */ - sdev->fw_vht_enabled = values[mib_index].u.boolValue; - else - SLSI_WARN(sdev, "Error reading VHT enabled mib\n"); - if (values[++mib_index].type == SLSI_MIB_TYPE_OCTET) { /* HT capabilities */ - if (values[mib_index].u.octetValue.dataLength >= 4) - memcpy(&sdev->fw_ht_cap, values[mib_index].u.octetValue.data, 4); - else - SLSI_WARN(sdev, "Error reading HT capabilities\n"); - } else { - SLSI_WARN(sdev, "Error reading HT capabilities\n"); - } - if (values[++mib_index].type == SLSI_MIB_TYPE_OCTET) { /* VHT capabilities */ - if (values[mib_index].u.octetValue.dataLength >= 4) - memcpy(&sdev->fw_vht_cap, values[mib_index].u.octetValue.data, 4); - else - SLSI_WARN(sdev, "Error reading VHT capabilities\n"); - } else { - SLSI_WARN(sdev, "Error reading VHT capabilities\n"); - } - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { /* HARDWARE_PLATFORM */ - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT); - sdev->plat_info_mib.plat_build = values[mib_index].u.uintValue; - } else { - SLSI_WARN(sdev, "Error reading Hardware platform\n"); - } - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { /* REG_DOM_VERSION */ - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT); - sdev->reg_dom_version = values[mib_index].u.uintValue; - } else { - SLSI_WARN(sdev, "Error reading Reg domain version\n"); - } - - /* NAN enabled? */ - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { - sdev->nan_enabled = values[mib_index].u.boolValue; - } else { - sdev->nan_enabled = false; - SLSI_WARN(sdev, "Error reading NAN enabled mib\n"); - } - SLSI_DBG1(sdev, SLSI_CFG80211, "Value for NAN enabled mib : %d\n", sdev->nan_enabled); - - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { /* UnifiForcedScheduleDuration */ - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT); - sdev->fw_dwell_time = values[mib_index].u.uintValue; - } else { - SLSI_WARN(sdev, "Error reading UnifiForcedScheduleDuration\n"); - } - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (values[++mib_index].type == SLSI_MIB_TYPE_OCTET) { /* 5Ghz Allowed Channels */ - if (values[mib_index].u.octetValue.dataLength >= 8) { - memcpy(&sdev->wifi_sharing_5ghz_channel, values[mib_index].u.octetValue.data, 8); - slsi_extract_valid_wifi_sharing_channels(sdev); - } else { - SLSI_WARN(sdev, "Error reading 5Ghz Allowed Channels\n"); - } - } else { - SLSI_WARN(sdev, "Error reading 5Ghz Allowed Channels\n"); - } -#endif - -#ifdef CONFIG_SCSC_WLAN_AP_INFO_FILE - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* Dual band concurrency */ - sdev->dualband_concurrency = values[mib_index].u.boolValue; - else - SLSI_WARN(sdev, "Error reading dual band concurrency\n"); - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) /* max client for soft AP */ - sdev->softap_max_client = values[mib_index].u.uintValue; - else - SLSI_WARN(sdev, "Error reading SoftAP max client\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* Mac Randomization enable? */ - sdev->fw_mac_randomization_enabled = values[mib_index].u.boolValue; - else - SLSI_WARN(sdev, "Error reading Mac Randomization Support\n"); -#endif - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { /* Disable ch12/ch13 */ - sdev->device_config.disable_ch12_ch13 = values[mib_index].u.boolValue; - SLSI_DBG1(sdev, SLSI_CFG80211, "Value for default country without ch12/13 mib: %d\n", - sdev->device_config.disable_ch12_ch13); - } else { - SLSI_WARN(sdev, "Error reading default country without ch12/13 mib\n"); - } -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* Enhanced Arp Detect Support */ - sdev->device_config.fw_enhanced_arp_detect_supported = values[mib_index].u.boolValue; - else - SLSI_WARN(sdev, "Error reading Enhanced Arp Detect Support mib\n"); -#endif - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* APF Support */ - sdev->device_config.fw_apf_supported = values[mib_index].u.boolValue; - else - SLSI_WARN(sdev, "Error reading APF Support mib\n"); - - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* 40MHz for Soft AP */ - sdev->fw_SoftAp_2g_40mhz_enabled = values[mib_index].u.boolValue; - else - SLSI_WARN(sdev, "Error reading 40MHz for Soft AP\n"); - - kfree(values); - } - kfree(mibrsp.data); - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - slsi_check_num_radios(sdev); -#endif - return r; -} - -int slsi_set_mib_roam(struct slsi_dev *dev, struct net_device *ndev, u16 psid, int value) -{ - struct slsi_mib_data mib_data = { 0, NULL }; - int error = SLSI_MIB_STATUS_FAILURE; - - if (slsi_mib_encode_int(&mib_data, psid, value, 0) == SLSI_MIB_STATUS_SUCCESS) - if (mib_data.dataLength) { - error = slsi_mlme_set(dev, ndev, mib_data.data, mib_data.dataLength); - if (error) - SLSI_ERR(dev, "Err Setting MIB failed. error = %d\n", error); - kfree(mib_data.data); - } - - return error; -} - -#ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA -int slsi_set_mib_preferred_antenna(struct slsi_dev *dev, u16 value) -{ - struct slsi_mib_data mib_data = { 0, NULL }; - int error = SLSI_MIB_STATUS_FAILURE; - - if (slsi_mib_encode_uint(&mib_data, SLSI_PSID_UNIFI_PREFERRED_ANTENNA_BITMAP, - value, 0) == SLSI_MIB_STATUS_SUCCESS) - if (mib_data.dataLength) { - error = slsi_mlme_set(dev, NULL, mib_data.data, mib_data.dataLength); - if (error) - SLSI_ERR(dev, "Err Setting MIB failed. error = %d\n", error); - kfree(mib_data.data); - } - - return error; -} -#endif - -void slsi_reset_throughput_stats(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct slsi_mib_data mib_data = { 0, NULL }; - int error = SLSI_MIB_STATUS_FAILURE; - - if (slsi_mib_encode_int(&mib_data, SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, 0, 0) == SLSI_MIB_STATUS_SUCCESS) - if (mib_data.dataLength) { - error = slsi_mlme_set(sdev, dev, mib_data.data, mib_data.dataLength); - if (error) - SLSI_ERR(sdev, "Err Setting MIB failed. error = %d\n", error); - kfree(mib_data.data); - } -} - -int slsi_get_mib_roam(struct slsi_dev *sdev, u16 psid, int *mib_value) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - int rx_len = 0; - int r; - struct slsi_mib_get_entry get_values[] = { { psid, { 0, 0 } } }; - - r = slsi_mib_encode_get_list(&mibreq, sizeof(get_values) / sizeof(struct slsi_mib_get_entry), get_values); - if (r != SLSI_MIB_STATUS_SUCCESS) - return -ENOMEM; - - mibrsp.dataLength = 64; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, mibrsp.data, mibrsp.dataLength, &rx_len); - kfree(mibreq.data); - - if (r == 0) { - struct slsi_mib_value *values; - - mibrsp.dataLength = (u32)rx_len; - - values = slsi_mib_decode_get_list(&mibrsp, sizeof(get_values) / sizeof(struct slsi_mib_get_entry), get_values); - - if (!values) { - kfree(mibrsp.data); - return -EINVAL; - } - - WARN_ON(values[0].type == SLSI_MIB_TYPE_OCTET || - values[0].type == SLSI_MIB_TYPE_NONE); - - if (values[0].type == SLSI_MIB_TYPE_INT) - *mib_value = (int)(values->u.intValue); - else if (values[0].type == SLSI_MIB_TYPE_UINT) - *mib_value = (int)(values->u.uintValue); - else if (values[0].type == SLSI_MIB_TYPE_BOOL) - *mib_value = (int)(values->u.boolValue); - - SLSI_DBG2(sdev, SLSI_MLME, "MIB value = %d\n", *mib_value); - kfree(values); - } else { - SLSI_ERR(sdev, "Mib read failed (error: %d)\n", r); - } - - kfree(mibrsp.data); - return r; -} - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE -int slsi_mib_get_gscan_cap(struct slsi_dev *sdev, struct slsi_nl_gscan_capabilities *cap) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - int rx_len = 0; - int r; - static const struct slsi_mib_get_entry get_values[] = { { SLSI_PSID_UNIFI_GOOGLE_MAX_NUMBER_OF_PERIODIC_SCANS, { 0, 0 } }, - { SLSI_PSID_UNIFI_GOOGLE_MAX_RSSI_SAMPLE_SIZE, { 0, 0 } }, - { SLSI_PSID_UNIFI_GOOGLE_MAX_HOTLIST_APS, { 0, 0 } }, - { SLSI_PSID_UNIFI_GOOGLE_MAX_SIGNIFICANT_WIFI_CHANGE_APS, { 0, 0 } }, - { SLSI_PSID_UNIFI_GOOGLE_MAX_BSSID_HISTORY_ENTRIES, { 0, 0 } },}; - - r = slsi_mib_encode_get_list(&mibreq, sizeof(get_values) / sizeof(struct slsi_mib_get_entry), get_values); - if (r != SLSI_MIB_STATUS_SUCCESS) - return -ENOMEM; - - mibrsp.dataLength = 64; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, mibrsp.data, mibrsp.dataLength, &rx_len); - kfree(mibreq.data); - - if (r == 0) { - struct slsi_mib_value *values; - - mibrsp.dataLength = (u32)rx_len; - - values = slsi_mib_decode_get_list(&mibrsp, sizeof(get_values) / sizeof(struct slsi_mib_get_entry), get_values); - - if (!values) { - kfree(mibrsp.data); - return -EINVAL; - } - - if (values[0].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[0].type, SLSI_MIB_TYPE_UINT); - cap->max_scan_buckets = values[0].u.uintValue; - } - - if (values[1].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[1].type, SLSI_MIB_TYPE_UINT); - cap->max_rssi_sample_size = values[1].u.uintValue; - } - - if (values[2].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[2].type, SLSI_MIB_TYPE_UINT); - cap->max_hotlist_aps = values[2].u.uintValue; - } - - if (values[3].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[3].type, SLSI_MIB_TYPE_UINT); - cap->max_significant_wifi_change_aps = values[3].u.uintValue; - } - - if (values[4].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[4].type, SLSI_MIB_TYPE_UINT); - cap->max_bssid_history_entries = values[4].u.uintValue; - } - - kfree(values); - } - kfree(mibrsp.data); - return r; -} -#endif - -int slsi_mib_get_apf_cap(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - int data_length = 0; - int r = 0; - static const struct slsi_mib_get_entry get_values[] = { - { SLSI_PSID_UNIFI_APF_VERSION, { 0, 0 } }, /* to get the supported APF version*/ - { SLSI_PSID_UNIFI_APF_MAX_SIZE, { 0, 0 } } /* to get APF_MAX_SIZE*/ - }; - - r = slsi_mib_encode_get_list(&mibreq, (sizeof(get_values) / sizeof(struct slsi_mib_get_entry)), - get_values); - if (r != SLSI_MIB_STATUS_SUCCESS) - return -ENOMEM; - - /* 15*2 bytes for 2 Mib's */ - mibrsp.dataLength = 30; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_NET_DBG1(dev, SLSI_MLME, "failed to allocate memory\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, dev, mibreq.data, mibreq.dataLength, mibrsp.data, - mibrsp.dataLength, &data_length); - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = (u32)data_length; - values = slsi_mib_decode_get_list(&mibrsp, - (sizeof(get_values) / sizeof(struct slsi_mib_get_entry)), get_values); - if (!values) { - SLSI_NET_DBG1(dev, SLSI_MLME, "mib decode list failed\n"); - kfree(mibrsp.data); - return -ENOMEM; - } - - if (values[0].type == SLSI_MIB_TYPE_UINT) - sdev->device_config.apf_cap.version = values[0].u.uintValue; /* supported APF version */ - else - SLSI_ERR(sdev, "invalid type. index:%d\n", 0); - if (values[1].type == SLSI_MIB_TYPE_UINT) - sdev->device_config.apf_cap.max_length = values[1].u.uintValue; /* APF_MAX_LENGTH */ - else - SLSI_ERR(sdev, "invalid type. index:%d\n", 1); - } else { - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_get_req failed(result:0x%4x)\n", r); - } - - kfree(mibrsp.data); - kfree(values); - return r; -} - -int slsi_mib_get_rtt_cap(struct slsi_dev *sdev, struct net_device *dev, struct slsi_rtt_capabilities *cap) -{ - struct slsi_mib_data supported_rtt_capab = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - - struct slsi_mib_get_entry get_values[] = { { SLSI_PSID_UNIFI_RTT_CAPABILITIES, { 0, 0 } } }; - - mibrsp.dataLength = 64; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - kfree(mibrsp.data); - return -ENOMEM; - } - - values = slsi_read_mibs(sdev, dev, get_values, 1, &mibrsp); - if (!values) { - kfree(mibrsp.data); - return -EINVAL; - } - - if (values[0].type != SLSI_MIB_TYPE_OCTET) { - SLSI_ERR(sdev, "Invalid type (%d) for SLSI_PSID_UNIFI_RTT_CAPABILITIES", values[0].type); - kfree(mibrsp.data); - kfree(values); - return -EINVAL; - } - supported_rtt_capab = values[0].u.octetValue; - cap->rtt_one_sided_supported = supported_rtt_capab.data[0]; - cap->rtt_ftm_supported = supported_rtt_capab.data[1]; - cap->lci_support = supported_rtt_capab.data[2]; - cap->lcr_support = supported_rtt_capab.data[3]; - cap->responder_supported = supported_rtt_capab.data[4]; - cap->preamble_support = supported_rtt_capab.data[5]; - cap->bw_support = supported_rtt_capab.data[6]; - cap->mc_version = supported_rtt_capab.data[7]; - - kfree(values); - kfree(mibrsp.data); - return 0; -} - -struct slsi_peer *slsi_peer_add(struct slsi_dev *sdev, struct net_device *dev, u8 *peer_address, u16 aid) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = NULL; - u16 queueset = 0; - - if (WARN_ON(!aid)) { - SLSI_NET_ERR(dev, "Invalid aid(0) received\n"); - return NULL; - } - queueset = MAP_AID_TO_QS(aid); - - /* MUST only be called from the control path that has acquired the lock */ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - if (WARN_ON(!ndev_vif->activated)) - return NULL; - - if (!peer_address) { - SLSI_NET_WARN(dev, "Peer without address\n"); - return NULL; - } - - peer = slsi_get_peer_from_mac(sdev, dev, peer_address); - if (peer) { - if (ndev_vif->sta.tdls_enabled && (peer->queueset == 0)) { - SLSI_NET_DBG3(dev, SLSI_CFG80211, "TDLS enabled and its station queueset\n"); - } else { - SLSI_NET_WARN(dev, "Peer (MAC:%pM) already exists\n", peer_address); - return NULL; - } - } - - if (slsi_get_peer_from_qs(sdev, dev, queueset)) { - SLSI_NET_WARN(dev, "Peer (queueset:%d) already exists\n", queueset); - return NULL; - } - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "%pM, aid:%d\n", peer_address, aid); - - peer = ndev_vif->peer_sta_record[queueset]; - if (!peer) { - /* If it reaches here, something has gone wrong */ - SLSI_NET_ERR(dev, "Peer (queueset:%d) is NULL\n", queueset); - return NULL; - } - - peer->aid = aid; - peer->queueset = queueset; - SLSI_ETHER_COPY(peer->address, peer_address); - peer->assoc_ie = NULL; - peer->assoc_resp_ie = NULL; - peer->is_wps = false; - peer->connected_state = SLSI_STA_CONN_STATE_DISCONNECTED; - /* Initialise the Station info */ - slsi_peer_reset_stats(sdev, dev, peer); - ratelimit_state_init(&peer->sinfo_mib_get_rs, SLSI_SINFO_MIB_ACCESS_TIMEOUT, 0); - - if (scsc_wifi_fcq_ctrl_q_init(&peer->ctrl_q) < 0) { - SLSI_NET_ERR(dev, "scsc_wifi_fcq_ctrl_q_init failed\n"); - return NULL; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (scsc_wifi_fcq_unicast_qset_init(dev, &peer->data_qs, peer->queueset, sdev, ndev_vif->ifnum, peer) < 0) { -#else - if (scsc_wifi_fcq_unicast_qset_init(dev, &peer->data_qs, peer->queueset, sdev, ndev_vif->ifnum, peer) < 0) { -#endif - SLSI_NET_ERR(dev, "scsc_wifi_fcq_unicast_qset_init failed\n"); - scsc_wifi_fcq_ctrl_q_deinit(&peer->ctrl_q); - return NULL; - } - - /* A peer is only valid once all the data is initialised - * otherwise a process could check the flag and start to read - * uninitialised data. - */ - - if (ndev_vif->sta.tdls_enabled) - ndev_vif->sta.tdls_peer_sta_records++; - else - ndev_vif->peer_sta_records++; - - ndev_vif->cfg80211_sinfo_generation++; - skb_queue_head_init(&peer->buffered_frames); - - /* For TDLS this flag will be set while moving the packets from STAQ to TDLSQ */ - /* TODO: changes for moving packets is removed for now. Enable this when these data path changes go in*/ -/* if (!ndev_vif->sta.tdls_enabled) - * peer->valid = true; - */ - peer->valid = true; - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "created station peer %pM AID:%d\n", peer->address, aid); - return peer; -} - -void slsi_peer_reset_stats(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_UNUSED_PARAMETER(sdev); - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "Peer:%pM\n", peer->address); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - memset(&peer->sinfo, 0x00, sizeof(peer->sinfo)); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) - peer->sinfo.filled = BIT(NL80211_STA_INFO_RX_BYTES) | - BIT(NL80211_STA_INFO_TX_BYTES) | - BIT(NL80211_STA_INFO_RX_PACKETS) | - BIT(NL80211_STA_INFO_TX_PACKETS) | - BIT(NL80211_STA_INFO_RX_DROP_MISC) | - BIT(NL80211_STA_INFO_TX_FAILED) | - BIT(NL80211_STA_INFO_SIGNAL) | - BIT(NL80211_STA_INFO_BSS_PARAM); -#else - peer->sinfo.filled = STATION_INFO_RX_BYTES | - STATION_INFO_TX_BYTES | - STATION_INFO_RX_PACKETS | - STATION_INFO_TX_PACKETS | - STATION_INFO_RX_DROP_MISC | - STATION_INFO_TX_FAILED | - STATION_INFO_SIGNAL | - STATION_INFO_BSS_PARAM; -#endif -} - -void slsi_dump_stats(struct net_device *dev) -{ - SLSI_UNUSED_PARAMETER(dev); - - SLSI_INFO_NODEV("slsi_hanged_event_count: %d\n", slsi_hanged_event_count); -} - -enum slsi_wlan_vendor_attr_hanged_event { - SLSI_WLAN_VENDOR_ATTR_HANGED_EVENT_PANIC_CODE = 1, - SLSI_WLAN_VENDOR_ATTR_HANGED_EVENT_MAX -}; - -int slsi_send_hanged_vendor_event(struct slsi_dev *sdev, u16 scsc_panic_code) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - struct sk_buff *skb; - int length = sizeof(scsc_panic_code); - - slsi_hanged_event_count++; - SLSI_INFO(sdev, "Sending SLSI_NL80211_VENDOR_HANGED_EVENT , count: %d, reason =0x%2x\n", slsi_hanged_event_count, scsc_panic_code); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, length, SLSI_NL80211_VENDOR_HANGED_EVENT, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, length, SLSI_NL80211_VENDOR_HANGED_EVENT, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate SKB for vendor hanged event"); - return -ENOMEM; - } - - if (nla_put(skb, SLSI_WLAN_VENDOR_ATTR_HANGED_EVENT_PANIC_CODE, length, &scsc_panic_code)) { - SLSI_ERR_NODEV("Failed nla_put for panic code\n"); - slsi_kfree_skb(skb); - return -EINVAL; - } - cfg80211_vendor_event(skb, GFP_KERNEL); - -#endif - return 0; -} - -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -int slsi_send_forward_beacon_vendor_event(struct slsi_dev *sdev, const u8 *ssid, const int ssid_len, const u8 *bssid, - u8 channel, const u16 beacon_int, const u64 timestamp, const u64 sys_time) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - struct sk_buff *skb; - u8 err = 0; - struct net_device *dev; - struct netdev_vif *ndev_vif; - - dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(dev); - - SLSI_DBG2(sdev, SLSI_CFG80211, "Sending SLSI_NL80211_VENDOR_FORWARD_BEACON\n"); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, &ndev_vif->wdev, NLMSG_DEFAULT_SIZE, - SLSI_NL80211_VENDOR_FORWARD_BEACON, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, - SLSI_NL80211_VENDOR_FORWARD_BEACON, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate SKB for vendor forward_beacon event\n"); - return -ENOMEM; - } - - err |= nla_put(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_SSID, ssid_len, ssid); - err |= nla_put(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_BSSID, ETH_ALEN, bssid); - err |= nla_put_u8(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_CHANNEL, channel); - err |= nla_put_u16(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_BCN_INTERVAL, beacon_int); - err |= nla_put_u32(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_TIME_STAMP1, (timestamp & 0x00000000FFFFFFFF)); - err |= nla_put_u32(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_TIME_STAMP2, - ((timestamp >> 32) & 0x00000000FFFFFFFF)); - err |= nla_put_u64_64bit(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_SYS_TIME, sys_time, 0); - - if (err) { - SLSI_ERR_NODEV("Failed nla_put for forward_beacon\n"); - slsi_kfree_skb(skb); - return -EINVAL; - } - cfg80211_vendor_event(skb, GFP_KERNEL); - -#endif - return 0; -} - -int slsi_send_forward_beacon_abort_vendor_event(struct slsi_dev *sdev, u16 reason_code) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - struct sk_buff *skb; - u8 err = 0; - struct net_device *dev; - struct netdev_vif *ndev_vif; - - dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(dev); - - SLSI_INFO(sdev, "Sending SLSI_NL80211_VENDOR_FORWARD_BEACON_ABORT\n"); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, &ndev_vif->wdev, sizeof(reason_code), - SLSI_NL80211_VENDOR_FORWARD_BEACON_ABORT, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, sizeof(reason_code), - SLSI_NL80211_VENDOR_FORWARD_BEACON_ABORT, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate SKB for vendor forward_beacon_abort event\n"); - return -ENOMEM; - } - - err = nla_put_u16(skb, SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_ABORT, reason_code); - - if (err) { - SLSI_ERR_NODEV("Failed nla_put for beacon_recv_abort\n"); - slsi_kfree_skb(skb); - return -EINVAL; - } - cfg80211_vendor_event(skb, GFP_KERNEL); - -#endif - return 0; -} -#endif - -#ifdef CONFIG_SCSC_WLAN_HANG_TEST -int slsi_test_send_hanged_vendor_event(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_INFO(ndev_vif->sdev, "Test FORCE HANG\n"); - return slsi_send_hanged_vendor_event(ndev_vif->sdev, SCSC_PANIC_CODE_HOST << 15); -} -#endif - -static bool slsi_search_ies_for_qos_indicators(struct slsi_dev *sdev, u8 *ies, int ies_len) -{ - SLSI_UNUSED_PARAMETER(sdev); - - if (cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len)) { - SLSI_DBG1(sdev, SLSI_CFG80211, "QOS enabled due to WLAN_EID_HT_CAPABILITY\n"); - return true; - } - if (cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, ies_len)) { - SLSI_DBG1(sdev, SLSI_CFG80211, "QOS enabled due to WLAN_EID_VHT_CAPABILITY\n"); - return true; - } - if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WMM, ies, ies_len)) { - SLSI_DBG1(sdev, SLSI_CFG80211, "QOS enabled due to WLAN_OUI_TYPE_MICROSOFT_WMM\n"); - return true; - } - return false; -} - -void slsi_peer_update_assoc_req(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 id = fapi_get_u16(skb, id); - - /* MUST only be called from the control path that has acquired the lock */ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - switch (id) { - case MLME_CONNECTED_IND: - case MLME_PROCEDURE_STARTED_IND: - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_AP && - ndev_vif->vif_type != FAPI_VIFTYPE_STATION)) { - slsi_kfree_skb(skb); - return; - } - break; - default: - slsi_kfree_skb(skb); - WARN_ON(1); - return; - } - - slsi_kfree_skb(peer->assoc_ie); - peer->assoc_ie = NULL; - peer->capabilities = 0; - - if (fapi_get_datalen(skb)) { - int mgmt_hdr_len; - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - struct netdev_vif *ndev_vif = netdev_priv(dev); - - /* Update the skb to just point to the frame */ - skb_pull(skb, fapi_get_siglen(skb)); - - if (ieee80211_is_assoc_req(mgmt->frame_control)) { - mgmt_hdr_len = (mgmt->u.assoc_req.variable - (u8 *)mgmt); - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) - peer->capabilities = le16_to_cpu(mgmt->u.assoc_req.capab_info); - } else if (ieee80211_is_reassoc_req(mgmt->frame_control)) { - mgmt_hdr_len = (mgmt->u.reassoc_req.variable - (u8 *)mgmt); - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) - peer->capabilities = le16_to_cpu(mgmt->u.reassoc_req.capab_info); - } else { - WARN_ON(1); - slsi_kfree_skb(skb); - return; - } - - skb_pull(skb, mgmt_hdr_len); - - peer->assoc_ie = skb; - peer->sinfo.assoc_req_ies = skb->data; - peer->sinfo.assoc_req_ies_len = skb->len; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) - peer->sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; -#endif - peer->qos_enabled = slsi_search_ies_for_qos_indicators(sdev, skb->data, skb->len); - } -} - -void slsi_peer_update_assoc_rsp(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 id = fapi_get_u16(skb, id); - - SLSI_UNUSED_PARAMETER(sdev); - - /* MUST only be called from the control path that has acquired the lock */ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) - goto exit_with_warnon; - - if (id != MLME_CONNECT_IND && id != MLME_ROAMED_IND && id != MLME_REASSOCIATE_IND) { - SLSI_NET_ERR(dev, "Unexpected id =0x%4x\n", id); - goto exit_with_warnon; - } - - slsi_kfree_skb(peer->assoc_resp_ie); - peer->assoc_resp_ie = NULL; - peer->capabilities = 0; - if (fapi_get_datalen(skb)) { - int mgmt_hdr_len; - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - - /* Update the skb to just point to the frame */ - skb_pull(skb, fapi_get_siglen(skb)); - - if (ieee80211_is_assoc_resp(mgmt->frame_control)) { - mgmt_hdr_len = (mgmt->u.assoc_resp.variable - (u8 *)mgmt); - peer->capabilities = le16_to_cpu(mgmt->u.assoc_resp.capab_info); - } else if (ieee80211_is_reassoc_resp(mgmt->frame_control)) { - mgmt_hdr_len = (mgmt->u.reassoc_resp.variable - (u8 *)mgmt); - peer->capabilities = le16_to_cpu(mgmt->u.reassoc_resp.capab_info); - } else { - goto exit_with_warnon; - } - - skb_pull(skb, mgmt_hdr_len); - peer->assoc_resp_ie = skb; - } - return; - -exit_with_warnon: - WARN_ON(1); - slsi_kfree_skb(skb); -} - -int slsi_peer_remove(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *buff_frame; - - SLSI_UNUSED_PARAMETER(sdev); - - /* MUST only be called from the control path that has acquired the lock */ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (!peer) { - SLSI_NET_WARN(dev, "peer=NULL"); - return -EINVAL; - } - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "%pM\n", peer->address); - - buff_frame = slsi_skb_dequeue(&peer->buffered_frames); - while (buff_frame) { - SLSI_NET_DBG3(dev, SLSI_MLME, "FLUSHING BUFFERED FRAMES\n"); - slsi_kfree_skb(buff_frame); - buff_frame = slsi_skb_dequeue(&peer->buffered_frames); - } - - slsi_rx_ba_stop_all(dev, peer); - - /* The information is no longer valid so first update the flag to ensure that - * another process doesn't try to use it any more. - */ - peer->valid = false; - peer->is_wps = false; - peer->connected_state = SLSI_STA_CONN_STATE_DISCONNECTED; - - if (slsi_is_tdls_peer(dev, peer)) - ndev_vif->sta.tdls_peer_sta_records--; - else - ndev_vif->peer_sta_records--; - - ndev_vif->cfg80211_sinfo_generation++; - - scsc_wifi_fcq_qset_deinit(dev, &peer->data_qs, sdev, ndev_vif->ifnum, peer); - scsc_wifi_fcq_ctrl_q_deinit(&peer->ctrl_q); - - slsi_kfree_skb(peer->assoc_ie); - slsi_kfree_skb(peer->assoc_resp_ie); - memset(peer, 0x00, sizeof(*peer)); - - return 0; -} - -int slsi_vif_activated(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_UNUSED_PARAMETER(sdev); - - /* MUST only be called from the control path that has acquired the lock */ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - /* MUST have cleared any peer records previously */ - WARN_ON(ndev_vif->peer_sta_records); - - if (WARN_ON(ndev_vif->activated)) - return -EALREADY; - - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) - /* Enable the Multicast queue set for AP mode */ - if (scsc_wifi_fcq_multicast_qset_init(dev, &ndev_vif->ap.group_data_qs, sdev, ndev_vif->ifnum) < 0) - return -EFAULT; - - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - /* MUST have cleared any tdls peer records previously */ - WARN_ON(ndev_vif->sta.tdls_peer_sta_records); - - ndev_vif->sta.tdls_peer_sta_records = 0; - ndev_vif->sta.tdls_enabled = false; - ndev_vif->sta.roam_in_progress = false; - ndev_vif->sta.nd_offload_enabled = true; - - memset(ndev_vif->sta.keepalive_host_tag, 0, sizeof(ndev_vif->sta.keepalive_host_tag)); - } - - ndev_vif->cfg80211_sinfo_generation = 0; - ndev_vif->peer_sta_records = 0; - ndev_vif->activated = true; - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - return 0; -} - -void slsi_vif_deactivated(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int i; - - /* MUST only be called from the control path that has acquired the lock */ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - /* The station type VIF is deactivated when the AP connection is lost */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - ndev_vif->sta.group_key_set = false; - ndev_vif->sta.vif_status = SLSI_VIF_STATUS_UNSPECIFIED; - memset(ndev_vif->sta.keepalive_host_tag, 0, sizeof(ndev_vif->sta.keepalive_host_tag)); - - /* delete the TSPEC entries (if any) if it is a STA vif */ - if (ndev_vif->iftype == NL80211_IFTYPE_STATION) - cac_delete_tspec_list(sdev); - - if (ndev_vif->sta.tdls_enabled) - WARN(ndev_vif->sta.tdls_peer_sta_records, "vif:%d, tdls_peer_sta_records:%d", ndev_vif->ifnum, ndev_vif->sta.tdls_peer_sta_records); - - if (ndev_vif->sta.sta_bss) { - slsi_cfg80211_put_bss(sdev->wiphy, ndev_vif->sta.sta_bss); - ndev_vif->sta.sta_bss = NULL; - } - ndev_vif->sta.tdls_enabled = false; -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - ndev_vif->is_wips_running = false; -#endif - } - - /* MUST be done first to ensure that other code doesn't treat the VIF as still active */ - ndev_vif->activated = false; - slsi_skb_queue_purge(&ndev_vif->rx_data.queue); - - for (i = 0; i < (SLSI_ADHOC_PEER_CONNECTIONS_MAX); i++) { - struct slsi_peer *peer = ndev_vif->peer_sta_record[i]; - - if (peer && peer->valid) { - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && peer->assoc_ie) - cfg80211_del_sta(dev, peer->address, GFP_KERNEL); - - slsi_spinlock_lock(&ndev_vif->peer_lock); - slsi_peer_remove(sdev, dev, peer); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - } - } - - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) { - memset(&ndev_vif->ap.last_disconnected_sta, 0, sizeof(ndev_vif->ap.last_disconnected_sta)); - scsc_wifi_fcq_qset_deinit(dev, &ndev_vif->ap.group_data_qs, sdev, ndev_vif->ifnum, NULL); - } - - if ((ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) || (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO)) { - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_NO_VIF); - sdev->p2p_group_exp_frame = SLSI_P2P_PA_INVALID; - } - - /* MUST be done last as lots of code is dependent on checking the vif_type */ - ndev_vif->vif_type = SLSI_VIFTYPE_UNSPECIFIED; - ndev_vif->set_power_mode = FAPI_POWERMANAGEMENTMODE_POWER_SAVE; - if (slsi_is_rf_test_mode_enabled()) { - SLSI_NET_ERR(dev, "*#rf# rf test mode set is enabled.\n"); - ndev_vif->set_power_mode = FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE; - } else { - ndev_vif->set_power_mode = FAPI_POWERMANAGEMENTMODE_POWER_SAVE; - } - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - - /* SHOULD have cleared any peer records */ - WARN(ndev_vif->peer_sta_records, "vif:%d, peer_sta_records:%d", ndev_vif->ifnum, ndev_vif->peer_sta_records); - - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - if (ndev_vif->sta.tdls_enabled) - WARN(ndev_vif->sta.tdls_peer_sta_records, "vif:%d, tdls_peer_sta_records:%d", - ndev_vif->ifnum, ndev_vif->sta.tdls_peer_sta_records); - - if (ndev_vif->sta.sta_bss) { - slsi_cfg80211_put_bss(sdev->wiphy, ndev_vif->sta.sta_bss); - ndev_vif->sta.sta_bss = NULL; - } - ndev_vif->sta.tdls_enabled = false; - } - - sdev->device_config.qos_info = -1; -} - -int slsi_sta_ieee80211_mode(struct net_device *dev, u16 current_bss_channel_frequency) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - const u8 *ie; - - ie = cfg80211_find_ie(WLAN_EID_VHT_OPERATION, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - if (ie) - return SLSI_80211_MODE_11AC; - - ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len); - if (ie) - return SLSI_80211_MODE_11N; - - if (current_bss_channel_frequency > 5000) - return SLSI_80211_MODE_11A; - - ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len); - if (ie) - return slsi_get_supported_mode(ie); - return -EINVAL; -} - -static int slsi_get_sta_mode(struct net_device *dev, const u8 *last_peer_mac) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct slsi_peer *last_peer; - const u8 *peer_ie; - - last_peer = slsi_get_peer_from_mac(sdev, dev, last_peer_mac); - - if (!last_peer) { - SLSI_NET_ERR(dev, "Peer not found\n"); - return -EINVAL; - } - - ndev_vif->ap.last_disconnected_sta.support_mode = 0; - if (cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, last_peer->assoc_ie->data, - last_peer->assoc_ie->len)) - ndev_vif->ap.last_disconnected_sta.support_mode = 3; - else if (cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, last_peer->assoc_ie->data, - last_peer->assoc_ie->len)) - ndev_vif->ap.last_disconnected_sta.support_mode = 1; - - if (ndev_vif->ap.mode == SLSI_80211_MODE_11AC) { /*AP supports VHT*/ - peer_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, last_peer->assoc_ie->data, - last_peer->assoc_ie->len); - if (peer_ie) - return SLSI_80211_MODE_11AC; - - peer_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, last_peer->assoc_ie->data, - last_peer->assoc_ie->len); - if (peer_ie) - return SLSI_80211_MODE_11N; - return SLSI_80211_MODE_11A; - } - if (ndev_vif->ap.mode == SLSI_80211_MODE_11N) { /*AP supports HT*/ - peer_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, last_peer->assoc_ie->data, - last_peer->assoc_ie->len); - if (peer_ie) - return SLSI_80211_MODE_11N; - if (ndev_vif->ap.channel_freq > 5000) - return SLSI_80211_MODE_11A; - peer_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, last_peer->assoc_ie->data, - last_peer->assoc_ie->len); - if (peer_ie) - return slsi_get_supported_mode(peer_ie); - } - - if (ndev_vif->ap.channel_freq > 5000) - return SLSI_80211_MODE_11A; - - if (ndev_vif->ap.mode == SLSI_80211_MODE_11G) { /*AP supports 11g mode */ - peer_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, last_peer->assoc_ie->data, - last_peer->assoc_ie->len); - if (peer_ie) - return slsi_get_supported_mode(peer_ie); - } - - return SLSI_80211_MODE_11B; -} - -int slsi_populate_bss_record(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - const u8 *ie, *ext_capab, *rm_capab, *ext_data, *rm_data, *bss_load; - u8 ext_capab_ie_len, rm_capab_ie_len; - bool neighbor_report_bit = 0, btm = 0; - u16 fw_tx_rate; - struct slsi_mib_get_entry get_values[] = { { SLSI_PSID_UNIFI_CURRENT_BSS_CHANNEL_FREQUENCY, { 0, 0 } }, - { SLSI_PSID_UNIFI_CURRENT_BSS_BANDWIDTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_CURRENT_BSS_NSS, {0, 0} }, - { SLSI_PSID_UNIFI_AP_MIMO_USED, {0, 0} }, - { SLSI_PSID_UNIFI_LAST_BSS_SNR, {0, 0} }, - { SLSI_PSID_UNIFI_LAST_BSS_RSSI, { 0, 0 } }, - { SLSI_PSID_UNIFI_ROAMING_COUNT, {0, 0} }, - { SLSI_PSID_UNIFI_LAST_BSS_TX_DATA_RATE, { 0, 0 } }, - { SLSI_PSID_UNIFI_ROAMING_AKM, {0, 0} } }; - - mibrsp.dataLength = 10 * ARRAY_SIZE(get_values); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes for interface MIBs\n", mibrsp.dataLength); - return -ENOMEM; - } - - values = slsi_read_mibs(sdev, dev, get_values, ARRAY_SIZE(get_values), &mibrsp); - - memset(&ndev_vif->sta.last_connected_bss, 0, sizeof(ndev_vif->sta.last_connected_bss)); - - if (!values) { - SLSI_NET_DBG1(dev, SLSI_MLME, "mib decode list failed\n"); - kfree(values); - kfree(mibrsp.data); - return -EINVAL; - } - - /* The Below sequence of reading the BSS Info related Mibs is very important */ - if (values[0].type != SLSI_MIB_TYPE_NONE) { /* CURRENT_BSS_CHANNEL_FREQUENCY */ - SLSI_CHECK_TYPE(sdev, values[0].type, SLSI_MIB_TYPE_UINT); - ndev_vif->sta.last_connected_bss.channel_freq = ((values[0].u.uintValue) / 2); - } - - if (values[1].type != SLSI_MIB_TYPE_NONE) { /* CURRENT_BSS_BANDWIDTH */ - SLSI_CHECK_TYPE(sdev, values[1].type, SLSI_MIB_TYPE_UINT); - ndev_vif->sta.last_connected_bss.bandwidth = values[1].u.uintValue; - } - - if (values[2].type != SLSI_MIB_TYPE_NONE) { /* CURRENT_BSS_NSS */ - SLSI_CHECK_TYPE(sdev, values[2].type, SLSI_MIB_TYPE_UINT); - ndev_vif->sta.last_connected_bss.antenna_mode = values[2].u.uintValue; - } - - if (values[3].type != SLSI_MIB_TYPE_NONE) { /* AP_MIMO_USED */ - SLSI_CHECK_TYPE(sdev, values[3].type, SLSI_MIB_TYPE_UINT); - ndev_vif->sta.last_connected_bss.mimo_used = values[3].u.uintValue; - } - - if (values[4].type != SLSI_MIB_TYPE_NONE) { /* SNR */ - SLSI_CHECK_TYPE(sdev, values[4].type, SLSI_MIB_TYPE_UINT); - ndev_vif->sta.last_connected_bss.snr = values[4].u.uintValue; - } - - if (values[5].type != SLSI_MIB_TYPE_NONE) { /* RSSI */ - SLSI_CHECK_TYPE(sdev, values[5].type, SLSI_MIB_TYPE_INT); - ndev_vif->sta.last_connected_bss.rssi = values[5].u.intValue; - } - - if (values[6].type != SLSI_MIB_TYPE_NONE) { /* ROAMING_COUNT */ - SLSI_CHECK_TYPE(sdev, values[6].type, SLSI_MIB_TYPE_UINT); - ndev_vif->sta.last_connected_bss.roaming_count = values[6].u.uintValue; - } - - if (values[7].type != SLSI_MIB_TYPE_NONE) { /* TX_DATA_RATE */ - SLSI_CHECK_TYPE(sdev, values[7].type, SLSI_MIB_TYPE_UINT); - fw_tx_rate = values[7].u.uintValue; - slsi_decode_fw_rate(fw_tx_rate, NULL, - (unsigned long *)(&ndev_vif->sta.last_connected_bss.tx_data_rate)); - } - - if (values[8].type != SLSI_MIB_TYPE_NONE) { /* ROAMING_AKM */ - SLSI_CHECK_TYPE(sdev, values[8].type, SLSI_MIB_TYPE_UINT); - ndev_vif->sta.last_connected_bss.roaming_akm = values[8].u.uintValue; - } - - kfree(values); - kfree(mibrsp.data); - - if (!ndev_vif->sta.sta_bss) { - SLSI_WARN(sdev, "Bss missing due to out of order msg from firmware!! Cannot collect Big Data\n"); - return -EINVAL; - } - - SLSI_ETHER_COPY(ndev_vif->sta.last_connected_bss.address, ndev_vif->sta.sta_bss->bssid); - - ndev_vif->sta.last_connected_bss.mode = slsi_sta_ieee80211_mode(dev, - ndev_vif->sta.last_connected_bss.channel_freq); - if (ndev_vif->sta.last_connected_bss.mode == -EINVAL) { - SLSI_ERR(sdev, "slsi_get_bss_info : Supported Rates IE is null"); - return -EINVAL; - } - - ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, SLSI_WLAN_OUI_TYPE_WFA_HS20_IND, - ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len); - if (ie) { - if ((ie[6] >> 4) == 0) - ndev_vif->sta.last_connected_bss.passpoint_version = 1; - else - ndev_vif->sta.last_connected_bss.passpoint_version = 2; - } - - ndev_vif->sta.last_connected_bss.noise_level = (ndev_vif->sta.last_connected_bss.rssi - - ndev_vif->sta.last_connected_bss.snr); - - ext_capab = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - rm_capab = cfg80211_find_ie(WLAN_EID_RRM_ENABLED_CAPABILITIES, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - bss_load = cfg80211_find_ie(WLAN_EID_QBSS_LOAD, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - - if (ext_capab) { - ext_capab_ie_len = ext_capab[1]; - ext_data = &ext_capab[2]; - if ((ext_capab_ie_len >= 2) && (ext_data[1] & - SLSI_WLAN_EXT_CAPA1_PROXY_ARP_ENABLED)) /*check bit12 is set or not */ - ndev_vif->sta.last_connected_bss.kvie |= 1 << 1; - if (ext_capab_ie_len >= 3) { - if (ext_data[2] & SLSI_WLAN_EXT_CAPA2_TFS_ENABLED) /*check bit16 is set or not */ - ndev_vif->sta.last_connected_bss.kvie |= 1 << 2; - if (ext_data[2] & SLSI_WLAN_EXT_CAPA2_WNM_SLEEP_ENABLED) /*check bit17 is set or not */ - ndev_vif->sta.last_connected_bss.kvie |= 1 << 3; - if (ext_data[2] & SLSI_WLAN_EXT_CAPA2_TIM_ENABLED) /*check bit18 is set or not */ - ndev_vif->sta.last_connected_bss.kvie |= 1 << 4; - /*check bit19 is set or not */ - if (ext_data[2] & SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED) { - ndev_vif->sta.last_connected_bss.kvie |= 1 << 5; - btm = 1; - } - if (ext_data[2] & SLSI_WLAN_EXT_CAPA2_DMS_ENABLED) /*check bit20 is set or not */ - ndev_vif->sta.last_connected_bss.kvie |= 1 << 6; - } - } - if (bss_load) - ndev_vif->sta.last_connected_bss.kvie |= 1; - if (rm_capab) { - rm_capab_ie_len = rm_capab[1]; - rm_data = &rm_capab[2]; - if (rm_capab_ie_len >= 1) { - neighbor_report_bit = SLSI_WLAN_RM_CAPA0_NEIGHBOR_REPORT_ENABLED & rm_data[0]; - if (SLSI_WLAN_RM_CAPA0_LINK_MEASUREMENT_ENABLED & rm_data[0]) - ndev_vif->sta.last_connected_bss.kvie |= 1 << 7; - if (neighbor_report_bit) - ndev_vif->sta.last_connected_bss.kvie |= 1 << 8; - if (SLSI_WLAN_RM_CAPA0_PASSIVE_MODE_ENABLED & rm_data[0]) - ndev_vif->sta.last_connected_bss.kvie |= 1 << 9; - if (SLSI_WLAN_RM_CAPA0_ACTIVE_MODE_ENABLED & rm_data[0]) - ndev_vif->sta.last_connected_bss.kvie |= 1 << 10; - if (SLSI_WLAN_RM_CAPA0_TABLE_MODE_ENABLED & rm_data[0]) - ndev_vif->sta.last_connected_bss.kvie |= 1 << 11; - } - } - if (!neighbor_report_bit && !btm && !bss_load) - ndev_vif->sta.last_connected_bss.kv = 0; - else if (neighbor_report_bit != 0 && (!btm && !bss_load)) - ndev_vif->sta.last_connected_bss.kv = 1; /*11k support */ - else if (!neighbor_report_bit && (btm || bss_load)) - ndev_vif->sta.last_connected_bss.kv = 2; /*11v support */ - else - ndev_vif->sta.last_connected_bss.kv = 3; /*11kv support */ - - return 0; -} - -static int slsi_fill_last_disconnected_sta_info(struct slsi_dev *sdev, struct net_device *dev, - const u8 *last_peer_mac, const u16 reason_code) -{ - int i; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *last_peer; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - u16 fw_tx_rate; - struct slsi_mib_get_entry get_values[] = { { SLSI_PSID_UNIFI_PEER_BANDWIDTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_CURRENT_PEER_NSS, {0, 0} }, - { SLSI_PSID_UNIFI_PEER_RSSI, { 0, 0 } }, - { SLSI_PSID_UNIFI_PEER_TX_DATA_RATE, { 0, 0 } } }; - - SLSI_ETHER_COPY(ndev_vif->ap.last_disconnected_sta.address, - last_peer_mac); - ndev_vif->ap.last_disconnected_sta.reason = reason_code; - ndev_vif->ap.last_disconnected_sta.mode = slsi_get_sta_mode(dev, last_peer_mac); - last_peer = slsi_get_peer_from_mac(sdev, dev, last_peer_mac); - if (!last_peer) { - SLSI_NET_ERR(dev, "Peer not found\n"); - return -EINVAL; - } - for (i = 0; i < ARRAY_SIZE(get_values); i++) - get_values[i].index[0] = last_peer->aid; - - ndev_vif->ap.last_disconnected_sta.rx_retry_packets = SLSI_DEFAULT_UNIFI_PEER_RX_RETRY_PACKETS; - ndev_vif->ap.last_disconnected_sta.rx_bc_mc_packets = SLSI_DEFAULT_UNIFI_PEER_RX_BC_MC_PACKETS; - ndev_vif->ap.last_disconnected_sta.capabilities = last_peer->capabilities; - ndev_vif->ap.last_disconnected_sta.bandwidth = SLSI_DEFAULT_UNIFI_PEER_BANDWIDTH; - ndev_vif->ap.last_disconnected_sta.antenna_mode = SLSI_DEFAULT_UNIFI_PEER_NSS; - ndev_vif->ap.last_disconnected_sta.rssi = SLSI_DEFAULT_UNIFI_PEER_RSSI; - ndev_vif->ap.last_disconnected_sta.tx_data_rate = SLSI_DEFAULT_UNIFI_PEER_TX_DATA_RATE; - - mibrsp.dataLength = 15 * ARRAY_SIZE(get_values); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes for interface MIBs\n", mibrsp.dataLength); - return -ENOMEM; - } - - values = slsi_read_mibs(sdev, dev, get_values, ARRAY_SIZE(get_values), &mibrsp); - - if (!values) { - SLSI_NET_DBG1(dev, SLSI_MLME, "mib decode list failed\n"); - kfree(values); - kfree(mibrsp.data); - return -EINVAL; - } - if (values[0].type != SLSI_MIB_TYPE_NONE) { /* LAST_PEER_BANDWIDTH */ - SLSI_CHECK_TYPE(sdev, values[0].type, SLSI_MIB_TYPE_INT); - ndev_vif->ap.last_disconnected_sta.bandwidth = values[0].u.intValue; - } - - if (values[1].type != SLSI_MIB_TYPE_NONE) { /*LAST_PEER_NSS*/ - SLSI_CHECK_TYPE(sdev, values[1].type, SLSI_MIB_TYPE_INT); - ndev_vif->ap.last_disconnected_sta.antenna_mode = values[1].u.intValue; - } - - if (values[2].type != SLSI_MIB_TYPE_NONE) { /* LAST_PEER_RSSI*/ - SLSI_CHECK_TYPE(sdev, values[2].type, SLSI_MIB_TYPE_INT); - ndev_vif->ap.last_disconnected_sta.rssi = values[2].u.intValue; - } - - if (values[3].type != SLSI_MIB_TYPE_NONE) { /* LAST_PEER_TX_DATA_RATE */ - SLSI_CHECK_TYPE(sdev, values[3].type, SLSI_MIB_TYPE_UINT); - fw_tx_rate = values[3].u.uintValue; - slsi_decode_fw_rate(fw_tx_rate, NULL, - (unsigned long *)&ndev_vif->ap.last_disconnected_sta.tx_data_rate); - } - - kfree(values); - kfree(mibrsp.data); - - return 0; -} - -int slsi_handle_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *peer_address, u16 reason, - u8 *disassoc_rsp_ie, int disassoc_rsp_ie_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - if (WARN_ON(!dev)) - goto exit; - - SLSI_NET_DBG3(dev, SLSI_MLME, "slsi_handle_disconnect(vif:%d)\n", ndev_vif->ifnum); - - /* MUST only be called from somewhere that has acquired the lock */ - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit; - } - - switch (ndev_vif->vif_type) { - case FAPI_VIFTYPE_STATION: - { - netif_carrier_off(dev); - - /* MLME-DISCONNECT-IND could indicate the completion of a MLME-DISCONNECT-REQ or - * the connection with the AP has been lost - */ - if (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTING) { - if (!peer_address) - SLSI_NET_WARN(dev, "Connection failure\n"); - } else if (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED) { - if (reason == FAPI_REASONCODE_SYNCHRONISATION_LOSS) - reason = 0; /*reason code to recognise beacon loss */ - else if (reason == FAPI_REASONCODE_KEEP_ALIVE_FAILURE) - reason = WLAN_REASON_DEAUTH_LEAVING;/* Change to a standard reason code */ - else if (reason >= 0x8200 && reason <= 0x82FF) - reason = reason & 0x00FF; - - if (ndev_vif->sta.is_wps) /* Ignore sending deauth or disassoc event to cfg80211 during WPS session */ - SLSI_NET_INFO(dev, "Ignoring Deauth notification to cfg80211 from the peer during WPS procedure\n"); - else { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) - cfg80211_disconnected(dev, reason, disassoc_rsp_ie, disassoc_rsp_ie_len, - false, GFP_KERNEL); -#else - cfg80211_disconnected(dev, reason, disassoc_rsp_ie, disassoc_rsp_ie_len, - GFP_KERNEL); -#endif - SLSI_NET_DBG3(dev, SLSI_MLME, "Received disconnect from AP, reason = %d\n", reason); - } - } else if (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_DISCONNECTING) { - /* Change keep alive and sync_loss reason code while sending to supplicant to a standard reason code */ - if (reason == FAPI_REASONCODE_KEEP_ALIVE_FAILURE || - reason == FAPI_REASONCODE_SYNCHRONISATION_LOSS) - reason = WLAN_REASON_DEAUTH_LEAVING; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) - cfg80211_disconnected(dev, reason, disassoc_rsp_ie, disassoc_rsp_ie_len, true, GFP_KERNEL); -#else - cfg80211_disconnected(dev, reason, disassoc_rsp_ie, disassoc_rsp_ie_len, GFP_KERNEL); -#endif - SLSI_NET_DBG3(dev, SLSI_MLME, "Completion of disconnect from AP\n"); - } else { - /* Vif status is in erronus state.*/ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) - cfg80211_disconnected(dev, reason, disassoc_rsp_ie, disassoc_rsp_ie_len, false, GFP_KERNEL); -#else - cfg80211_disconnected(dev, reason, disassoc_rsp_ie, disassoc_rsp_ie_len, GFP_KERNEL); -#endif - SLSI_NET_WARN(dev, "disconnect in wrong state vif_status(%d)\n", ndev_vif->sta.vif_status); - } - - ndev_vif->sta.is_wps = false; - - /* Populate bss records on incase of disconnection. - * For connection failure its not required. - */ - if (!(ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTING || - ndev_vif->sta.vif_status == SLSI_VIF_STATUS_UNSPECIFIED)) - slsi_populate_bss_record(dev); - - kfree(ndev_vif->sta.assoc_req_add_info_elem); - if (ndev_vif->sta.assoc_req_add_info_elem) { - ndev_vif->sta.assoc_req_add_info_elem = NULL; - ndev_vif->sta.assoc_req_add_info_elem_len = 0; - } -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - memset(&ndev_vif->enhanced_arp_stats, 0, sizeof(ndev_vif->enhanced_arp_stats)); - ndev_vif->enhanced_arp_detect_enabled = false; -#endif - slsi_mlme_del_vif(sdev, dev); - slsi_vif_deactivated(sdev, dev); - break; - } - case FAPI_VIFTYPE_AP: - { - struct slsi_peer *peer = NULL; - - peer = slsi_get_peer_from_mac(sdev, dev, peer_address); - if (!peer) { - SLSI_NET_DBG1(dev, SLSI_MLME, "peer NOT found by MAC address\n"); - goto exit; - } - - SLSI_NET_DBG3(dev, SLSI_MLME, "MAC:%pM\n", peer_address); - slsi_fill_last_disconnected_sta_info(sdev, dev, peer_address, reason); - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - if ((peer->connected_state == SLSI_STA_CONN_STATE_CONNECTED) || (peer->connected_state == SLSI_STA_CONN_STATE_DOING_KEY_CONFIG)) - cfg80211_del_sta(dev, peer->address, GFP_KERNEL); - - slsi_spinlock_lock(&ndev_vif->peer_lock); - slsi_peer_remove(sdev, dev, peer); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - - /* If last client disconnects (after WPA2 handshake) then take wakelock till group is removed - * to avoid possibility of delay in group removal if platform suspends at this point. - */ - if (ndev_vif->ap.p2p_gc_keys_set && (ndev_vif->peer_sta_records == 0)) { - SLSI_NET_DBG2(dev, SLSI_MLME, "P2PGO - Acquire wakelock after last client disconnection\n"); - slsi_wakelock(&sdev->wlan_wl); - } - break; - } - default: - SLSI_NET_WARN(dev, "mlme_disconnect_ind(vif:%d, unexpected vif type:%d)\n", ndev_vif->ifnum, ndev_vif->vif_type); - break; - } -exit: - return 0; -} - -int slsi_ps_port_control(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, enum slsi_sta_conn_state s) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_UNUSED_PARAMETER(sdev); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - switch (s) { - case SLSI_STA_CONN_STATE_DISCONNECTED: - SLSI_NET_DBG1(dev, SLSI_TX, "STA disconnected, SET : FCQ - Disabled\n"); - peer->authorized = false; - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && !ndev_vif->peer_sta_records) - (void)scsc_wifi_fcq_8021x_port_state(dev, &ndev_vif->ap.group_data_qs, SCSC_WIFI_FCQ_8021x_STATE_BLOCKED); - return scsc_wifi_fcq_8021x_port_state(dev, &peer->data_qs, SCSC_WIFI_FCQ_8021x_STATE_BLOCKED); - - case SLSI_STA_CONN_STATE_DOING_KEY_CONFIG: - SLSI_NET_DBG1(dev, SLSI_TX, "STA doing KEY config, SET : FCQ - Disabled\n"); - peer->authorized = false; - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && !ndev_vif->peer_sta_records) - (void)scsc_wifi_fcq_8021x_port_state(dev, &ndev_vif->ap.group_data_qs, SCSC_WIFI_FCQ_8021x_STATE_BLOCKED); - return scsc_wifi_fcq_8021x_port_state(dev, &peer->data_qs, SCSC_WIFI_FCQ_8021x_STATE_BLOCKED); - - case SLSI_STA_CONN_STATE_CONNECTED: - SLSI_NET_DBG1(dev, SLSI_TX, "STA connected, SET : FCQ - Enabled\n"); - peer->authorized = true; - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) - (void)scsc_wifi_fcq_8021x_port_state(dev, &ndev_vif->ap.group_data_qs, SCSC_WIFI_FCQ_8021x_STATE_OPEN); - return scsc_wifi_fcq_8021x_port_state(dev, &peer->data_qs, SCSC_WIFI_FCQ_8021x_STATE_OPEN); - - default: - SLSI_NET_DBG1(dev, SLSI_TX, "SET : FCQ - Disabled\n"); - peer->authorized = false; - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && !ndev_vif->peer_sta_records) - (void)scsc_wifi_fcq_8021x_port_state(dev, &ndev_vif->ap.group_data_qs, SCSC_WIFI_FCQ_8021x_STATE_BLOCKED); - return scsc_wifi_fcq_8021x_port_state(dev, &peer->data_qs, SCSC_WIFI_FCQ_8021x_STATE_BLOCKED); - } - - return 0; -} - -int slsi_set_uint_mib(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int value) -{ - struct slsi_mib_data mib_data = { 0, NULL }; - int r = 0; - - SLSI_DBG2(sdev, SLSI_MLME, "UINT MIB Set Request (PSID = 0x%04X, Value = %d)\n", psid, value); - - r = slsi_mib_encode_uint(&mib_data, psid, value, 0); - if (r == SLSI_MIB_STATUS_SUCCESS) { - if (mib_data.dataLength) { - r = slsi_mlme_set(sdev, dev, mib_data.data, mib_data.dataLength); - if (r != 0) - SLSI_ERR(sdev, "MIB (PSID = 0x%04X) set error = %d\n", psid, r); - kfree(mib_data.data); - } - } - return r; -} - -int slsi_send_max_transmit_msdu_lifetime(struct slsi_dev *dev, struct net_device *ndev, u32 msdu_lifetime) -{ -#ifdef CCX_MSDU_LIFETIME_MIB_NA - struct slsi_mib_data mib_data = { 0, NULL }; - int error = 0; - - if (slsi_mib_encode_uint(&mib_data, SLSI_PSID_DOT11_MAX_TRANSMIT_MSDU_LIFETIME, msdu_lifetime, 0) == SLSI_MIB_STATUS_SUCCESS) - if (mib_data.dataLength) { - error = slsi_mlme_set(dev, ndev, mib_data.data, mib_data.dataLength); - if (error) - SLSI_ERR(dev, "Err Sending max msdu lifetime failed. error = %d\n", error); - kfree(mib_data.data); - } - return error; -#endif - /* TODO: current firmware do not have this MIB yet */ - return 0; -} - -int slsi_read_max_transmit_msdu_lifetime(struct slsi_dev *dev, struct net_device *ndev, u32 *msdu_lifetime) -{ -#ifdef CCX_MSDU_LIFETIME_MIB_NA - struct slsi_mib_data mib_data = { 0, NULL }; - struct slsi_mib_data mib_res = { 0, NULL }; - struct slsi_mib_entry mib_val; - int error = 0; - int mib_rx_len = 0; - size_t len; - - SLSI_UNUSED_PARAMETER(ndev); - - mib_res.dataLength = 10; /* PSID header(5) + dot11MaxReceiveLifetime 4 bytes + status(1) */ - mib_res.data = kmalloc(mib_res.dataLength, GFP_KERNEL); - - if (!mib_res.data) - return -ENOMEM; - - slsi_mib_encode_get(&mib_data, SLSI_PSID_DOT11_MAX_TRANSMIT_MSDU_LIFETIME, 0); - error = slsi_mlme_get(dev, NULL, mib_data.data, mib_data.dataLength, - mib_res.data, mib_res.dataLength, &mib_rx_len); - kfree(mib_data.data); - - if (error) { - SLSI_ERR(dev, "Err Reading max msdu lifetime failed. error = %d\n", error); - kfree(mib_res.data); - return error; - } - - len = slsi_mib_decode(&mib_res, &mib_val); - - if (len != 8) { - kfree(mib_res.data); - return -EINVAL; - } - *msdu_lifetime = mib_val.value.u.uintValue; - - kfree(mib_res.data); - - return error; -#endif - /* TODO: current firmware do not have this MIB yet */ - return 0; -} - -void slsi_band_cfg_update(struct slsi_dev *sdev, int band) -{ - /* TODO: lock scan_mutex*/ - switch (band) { - case SLSI_FREQ_BAND_AUTO: - sdev->wiphy->bands[0] = sdev->device_config.band_2G; - sdev->wiphy->bands[1] = sdev->device_config.band_5G; - break; - case SLSI_FREQ_BAND_5GHZ: - sdev->wiphy->bands[0] = NULL; - sdev->wiphy->bands[1] = sdev->device_config.band_5G; - break; - case SLSI_FREQ_BAND_2GHZ: - sdev->wiphy->bands[0] = sdev->device_config.band_2G; - sdev->wiphy->bands[1] = NULL; - break; - default: - break; - } - wiphy_apply_custom_regulatory(sdev->wiphy, sdev->device_config.domain_info.regdomain); - slsi_update_supported_channels_regd_flags(sdev); -} - -int slsi_band_update(struct slsi_dev *sdev, int band) -{ - int i; - struct net_device *dev; - struct netdev_vif *ndev_vif; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - - SLSI_DBG3(sdev, SLSI_CFG80211, "supported_band:%d\n", band); - - if (band == sdev->device_config.supported_band) { - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return 0; - } - - sdev->device_config.supported_band = band; - - slsi_band_cfg_update(sdev, band); - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - /* If new band is auto(2.4GHz + 5GHz, no need to check for station connection.*/ - if (band == 0) - return 0; - - /* If station is connected on any rejected band, disconnect the station. */ - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (i = 1; i < (CONFIG_SCSC_WLAN_MAX_INTERFACES + 1); i++) { - dev = slsi_get_netdev_locked(sdev, i); - if (!dev) - break; - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - /** - * 1. vif should be activated and vif type should be station. - * 2. Station should be either in connecting or connected state. - * 3. if (new band is 5G and connection is on 2.4) or (new band is 2.4 and connection is 5) - * when all the above conditions are true drop the connection - * Do not wait for disconnect ind. - */ - if ((ndev_vif->activated) && (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTING || ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED) && - (ndev_vif->chan->hw_value <= 14 ? band == SLSI_FREQ_BAND_5GHZ : band == SLSI_FREQ_BAND_2GHZ)) { - int r; - - if (!ndev_vif->sta.sta_bss) { - SLSI_ERR(sdev, "slsi_mlme_disconnect failed, sta_bss is not available\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -EINVAL; - } - - r = slsi_mlme_disconnect(sdev, dev, ndev_vif->sta.sta_bss->bssid, WLAN_REASON_DEAUTH_LEAVING, true); - LOG_CONDITIONALLY(r != 0, SLSI_ERR(sdev, "slsi_mlme_disconnect(%pM) failed with %d\n", ndev_vif->sta.sta_bss->bssid, r)); - - r = slsi_handle_disconnect(sdev, dev, ndev_vif->sta.sta_bss->bssid, 0, NULL, 0); - LOG_CONDITIONALLY(r != 0, SLSI_ERR(sdev, "slsi_handle_disconnect(%pM) failed with %d\n", ndev_vif->sta.sta_bss->bssid, r)); - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - return 0; -} - -/* This takes care to free the SKB on failure */ -int slsi_send_gratuitous_arp(struct slsi_dev *sdev, struct net_device *dev) -{ - int ret = 0; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *arp; - struct ethhdr *ehdr; - static const u8 arp_hdr[] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01 }; - int arp_size = sizeof(arp_hdr) + ETH_ALEN + sizeof(ndev_vif->ipaddress) + ETH_ALEN + sizeof(ndev_vif->ipaddress); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "\n"); - - if (!ndev_vif->ipaddress) - return 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION)) - return -EINVAL; - if (WARN_ON(ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) - return -EINVAL; - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "IP:%pI4\n", &ndev_vif->ipaddress); - - arp = slsi_alloc_skb_headroom(sizeof(struct ethhdr) + arp_size, GFP_KERNEL); - if (WARN_ON(!arp)) - return -ENOMEM; - - /* The Ethernet header is accessed in the stack. */ - skb_reset_mac_header(arp); - - /* Ethernet Header */ - ehdr = (struct ethhdr *)skb_put(arp, sizeof(struct ethhdr)); - memset(ehdr->h_dest, 0xFF, ETH_ALEN); - SLSI_ETHER_COPY(ehdr->h_source, dev->dev_addr); - ehdr->h_proto = cpu_to_be16(ETH_P_ARP); - - /* Arp Data */ - memcpy(skb_put(arp, sizeof(arp_hdr)), arp_hdr, sizeof(arp_hdr)); - SLSI_ETHER_COPY(skb_put(arp, ETH_ALEN), dev->dev_addr); - memcpy(skb_put(arp, sizeof(ndev_vif->ipaddress)), &ndev_vif->ipaddress, sizeof(ndev_vif->ipaddress)); - memset(skb_put(arp, ETH_ALEN), 0xFF, ETH_ALEN); - memcpy(skb_put(arp, sizeof(ndev_vif->ipaddress)), &ndev_vif->ipaddress, sizeof(ndev_vif->ipaddress)); - - arp->dev = dev; - arp->protocol = ETH_P_ARP; - arp->ip_summed = CHECKSUM_UNNECESSARY; - arp->queue_mapping = slsi_netif_get_peer_queue(0, 0); /* Queueset 0 AC 0 */ - - ret = slsi_tx_data(sdev, dev, arp); - if (ret) - slsi_kfree_skb(arp); - - return ret; -} - -const u8 addr_mask[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -const u8 solicited_node_addr_mask[6] = { 0x33, 0x33, 0xff, 0x00, 0x00, 0x01 }; - -static void slsi_create_packet_filter_element(u8 filterid, - u8 pkt_filter_mode, - u8 num_pattern_desc, - struct slsi_mlme_pattern_desc *pattern_desc, - struct slsi_mlme_pkt_filter_elem *pkt_filter_elem, - u8 *pkt_filters_len) -{ - u8 pkt_filter_hdr[SLSI_PKT_FILTER_ELEM_HDR_LEN] = { 0xdd, /* vendor ie*/ - 0x00, /*Length to be filled*/ - 0x00, 0x16, 0x32, /*oui*/ - 0x02, - filterid, /*filter id to be filled*/ - pkt_filter_mode /* pkt filter mode to be filled */ - }; - u8 i, pattern_desc_len = 0; - - WARN_ON(num_pattern_desc > SLSI_MAX_PATTERN_DESC); - - memcpy(pkt_filter_elem->header, pkt_filter_hdr, SLSI_PKT_FILTER_ELEM_HDR_LEN); - pkt_filter_elem->num_pattern_desc = num_pattern_desc; - - for (i = 0; i < num_pattern_desc; i++) { - memcpy(&pkt_filter_elem->pattern_desc[i], &pattern_desc[i], sizeof(struct slsi_mlme_pattern_desc)); - pattern_desc_len += SLSI_PKT_DESC_FIXED_LEN + (2 * pattern_desc[i].mask_length); - } - - /*Update the length in the header*/ - pkt_filter_elem->header[1] = SLSI_PKT_FILTER_ELEM_FIXED_LEN + pattern_desc_len; - *pkt_filters_len += (SLSI_PKT_FILTER_ELEM_HDR_LEN + pattern_desc_len); - - SLSI_DBG3_NODEV(SLSI_MLME, "filterid=0x%x,pkt_filter_mode=0x%x,num_pattern_desc=0x%x\n", - filterid, pkt_filter_mode, num_pattern_desc); -} - -#define SLSI_SCREEN_OFF_FILTERS_COUNT 1 - -static int slsi_set_common_packet_filters(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc; - struct slsi_mlme_pkt_filter_elem pkt_filter_elem[1]; - u8 pkt_filters_len = 0, num_filters = 0; - - /*Opt out all broadcast and multicast packets (filter on I/G bit)*/ - pattern_desc.offset = 0; - pattern_desc.mask_length = 1; - pattern_desc.mask[0] = 0x01; - pattern_desc.pattern[0] = 0x01; - - slsi_create_packet_filter_element(SLSI_ALL_BC_MC_FILTER_ID, - FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP | FAPI_PACKETFILTERMODE_OPT_OUT, - 1, &pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - return slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); -} - -int slsi_set_arp_packet_filter(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc[SLSI_MAX_PATTERN_DESC]; - int num_pattern_desc = 0; - u8 pkt_filters_len = 0, num_filters = 0; - struct slsi_mlme_pkt_filter_elem pkt_filter_elem[3]; - int ret; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION)) - return -EINVAL; - - if (WARN_ON(!peer)) - return -EINVAL; - - if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) - return 0; - - /*Set the IP address while suspending as this will be used by firmware for ARP/NDP offloading*/ - slsi_mlme_set_ip_address(sdev, dev); -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - slsi_mlme_set_ipv6_address(sdev, dev); -#endif - - SLSI_NET_DBG2(dev, SLSI_MLME, "Set ARP filter\n"); - - /* Opt out all ARP requests*/ - num_pattern_desc = 0; - SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP); - num_pattern_desc++; - - /* ARP - Request */ - pattern_desc[num_pattern_desc].offset = 0x14; /*sizeof(struct ethhdr) + offsetof(ar_op)*/ - pattern_desc[num_pattern_desc].mask_length = 2; - pattern_desc[num_pattern_desc].mask[0] = 0xff; - pattern_desc[num_pattern_desc].mask[1] = 0xff; - pattern_desc[num_pattern_desc].pattern[0] = 0x00; - pattern_desc[num_pattern_desc].pattern[1] = 0x01; - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_ALL_ARP_FILTER_ID, - FAPI_PACKETFILTERMODE_OPT_OUT | FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); - if (ret) - return ret; - - /*Opt-in arp pakcet for device IP address*/ - num_pattern_desc = 0; - SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP); - num_pattern_desc++; - - pattern_desc[num_pattern_desc].offset = 0x26; /*filtering on Target IP Address*/ - pattern_desc[num_pattern_desc].mask_length = 4; - memcpy(pattern_desc[num_pattern_desc].mask, addr_mask, pattern_desc[num_pattern_desc].mask_length); - memcpy(pattern_desc[num_pattern_desc].pattern, &ndev_vif->ipaddress, pattern_desc[num_pattern_desc].mask_length); - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_LOCAL_ARP_FILTER_ID, - FAPI_PACKETFILTERMODE_OPT_IN | FAPI_PACKETFILTERMODE_OPT_IN_SLEEP, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); - if (ret) - return ret; - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - pkt_filters_len = 0; - num_filters = 0; - - /*Opt in the multicast NS packets for Local IP address in active mode*/ - num_pattern_desc = 0; - pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/ - pattern_desc[num_pattern_desc].mask_length = ETH_ALEN; - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask); - memcpy(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask, 3); - memcpy(&pattern_desc[num_pattern_desc].pattern[3], &ndev_vif->ipv6address.s6_addr[13], 3); /* last 3 bytes of IPv6 address*/ - num_pattern_desc++; - - /*filter on ethertype ARP*/ - SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD); - num_pattern_desc++; - - pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/ - pattern_desc[num_pattern_desc].mask_length = 1; - pattern_desc[num_pattern_desc].mask[0] = 0xff; - pattern_desc[num_pattern_desc].pattern[0] = 0x3a; - num_pattern_desc++; - - pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/ - pattern_desc[num_pattern_desc].mask_length = 1; - pattern_desc[num_pattern_desc].mask[0] = 0xff; - pattern_desc[num_pattern_desc].pattern[0] = 0x87; /* Neighbor Solicitation type in ICMPv6 */ - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_LOCAL_NS_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_IN, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); - if (ret) - return ret; -#endif - - return ret; -} - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER -int slsi_set_enhanced_pkt_filter(struct net_device *dev, u8 pkt_filter_enable) -{ - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct slsi_dev *sdev = netdev_vif->sdev; - int ret = 0; - int is_suspend = 0; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - is_suspend = sdev->device_config.user_suspend_mode; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - if (is_suspend) { - SLSI_ERR(sdev, "Host is in early suspend state.\n"); - return -EPERM; /* set_enhanced_pkt_filter should not be called after suspend */ - } - - sdev->enhanced_pkt_filter_enabled = pkt_filter_enable; - SLSI_INFO(sdev, "Enhanced packet filter is %s", (pkt_filter_enable ? "enabled" : "disabled")); - return ret; -} - -static int slsi_set_opt_out_unicast_packet_filter(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc; - u8 pkt_filters_len = 0; - int ret = 0; - struct slsi_mlme_pkt_filter_elem pkt_filter_elem; - - /* IPv4 packet */ - pattern_desc.offset = 0; /* destination mac address*/ - pattern_desc.mask_length = ETH_ALEN; - memset(pattern_desc.mask, 0xff, ETH_ALEN); - memcpy(pattern_desc.pattern, sdev->hw_addr, ETH_ALEN); - - slsi_create_packet_filter_element(SLSI_OPT_OUT_ALL_FILTER_ID, - FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP, - 1, &pattern_desc, - &pkt_filter_elem, &pkt_filters_len); - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, 1, &pkt_filter_elem); - - return ret; -} - -static int slsi_set_opt_in_tcp4_packet_filter(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc[2]; - u8 pkt_filters_len = 0; - int ret = 0; - struct slsi_mlme_pkt_filter_elem pkt_filter_elem; - - /* IPv4 packet */ - pattern_desc[0].offset = ETH_ALEN + ETH_ALEN; /* ethhdr->h_proto */ - pattern_desc[0].mask_length = 2; - pattern_desc[0].mask[0] = 0xff; /* Big endian 0xffff */ - pattern_desc[0].mask[1] = 0xff; - pattern_desc[0].pattern[0] = 0x08; /* Big endian 0x0800 */ - pattern_desc[0].pattern[1] = 0x00; - - /* dest.addr(6) + src.addr(6) + Protocol(2) = sizeof(struct ethhdr) = 14 */ - /* VER(1) + Svc(1) + TotalLen(2) + ID(2) + Flag&Fragmentation(2) + TTL(1) = 9 */ - pattern_desc[1].offset = 23; /* iphdr->protocol */ - pattern_desc[1].mask_length = 1; - pattern_desc[1].mask[0] = 0xff; - pattern_desc[1].pattern[0] = IPPROTO_TCP; /* 0x11 */ - slsi_create_packet_filter_element(SLSI_OPT_IN_TCP4_FILTER_ID, - FAPI_PACKETFILTERMODE_OPT_IN_SLEEP, - 2, - pattern_desc, - &pkt_filter_elem, - &pkt_filters_len); - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, 1, &pkt_filter_elem); - - return ret; -} - -static int slsi_set_opt_in_tcp6_packet_filter(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc[2]; - u8 pkt_filters_len = 0; - int ret = 0; - struct slsi_mlme_pkt_filter_elem pkt_filter_elem; - - /* IPv6 packet */ - pattern_desc[0].offset = ETH_ALEN + ETH_ALEN; /* ethhdr->h_proto */ - pattern_desc[0].mask_length = 2; - pattern_desc[0].mask[0] = 0xff; /* Big endian 0xffff */ - pattern_desc[0].mask[1] = 0xff; - pattern_desc[0].pattern[0] = 0x86; /* Big endian 0x86DD */ - pattern_desc[0].pattern[1] = 0xdd; - - pattern_desc[1].offset = sizeof(struct ethhdr) + 6; /*filtering on ipv6->next header*/ - pattern_desc[1].mask_length = 1; - pattern_desc[1].mask[0] = 0xff; - pattern_desc[1].pattern[0] = IPPROTO_TCP; - - slsi_create_packet_filter_element(SLSI_OPT_IN_TCP6_FILTER_ID, - FAPI_PACKETFILTERMODE_OPT_IN_SLEEP, - 2, - pattern_desc, - &pkt_filter_elem, - &pkt_filters_len); - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, 1, &pkt_filter_elem); - - return ret; -} -#endif - -#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER -int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled) -{ - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct slsi_dev *sdev = netdev_vif->sdev; - int ret = 0; - int is_suspend = 0; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - is_suspend = sdev->device_config.user_suspend_mode; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - if (is_suspend) { - SLSI_ERR(sdev, "Host is in early suspend state.\n"); - return -EPERM; /* set_enhanced_pkt_filter should not be called after suspend */ - } - - sdev->abnormal_multicast_pkt_filter_enabled = enabled; - SLSI_INFO(sdev, "Abnormal multicast packet filter is %s", (enabled ? "enabled" : "disabled")); - return ret; -} - -static int slsi_set_opt_out_abnormal_multicast_packet_filter(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc[3]; - u8 pkt_filters_len = 0; - int ret = 0; - struct slsi_mlme_pkt_filter_elem pkt_filter_elem; - - /* IPv4 packet */ - pattern_desc[0].offset = 0; /* destination mac address*/ - pattern_desc[0].mask_length = ETH_ALEN; - memset(pattern_desc[0].mask, 0xff, ETH_ALEN); - memcpy(pattern_desc[0].pattern, sdev->hw_addr, ETH_ALEN); - - pattern_desc[1].offset = ETH_ALEN + ETH_ALEN; /* ethhdr->h_proto == IPv4 */ - pattern_desc[1].mask_length = 2; - pattern_desc[1].mask[0] = 0xff; /* Big endian 0xffff */ - pattern_desc[1].mask[1] = 0xff; - pattern_desc[1].pattern[0] = 0x08; /* Big endian 0x0800 */ - pattern_desc[1].pattern[1] = 0x00; - - pattern_desc[2].offset = sizeof(struct ethhdr) + offsetof(struct iphdr, daddr); /* iphdr->daddr starts with 1110 */ - pattern_desc[2].mask_length = 1; - pattern_desc[2].mask[0] = 0xf0; - pattern_desc[2].pattern[0] = 0xe0; /* 224 */ - - slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, - FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP, - 3, pattern_desc, - &pkt_filter_elem, &pkt_filters_len); - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, 1, &pkt_filter_elem); - - return ret; -} -#endif - -static int slsi_set_multicast_packet_filters(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc; - u8 pkt_filters_len = 0, i, num_filters = 0; - int ret = 0; - struct slsi_mlme_pkt_filter_elem *pkt_filter_elem = NULL; - struct netdev_vif *ndev_vif = netdev_priv(dev); - u8 mc_filter_id, mc_filter_count; - - /* Multicast packets for registered multicast addresses to be opted in on screen off*/ - SLSI_NET_DBG2(dev, SLSI_MLME, "Set mc filters ,count =%d\n", ndev_vif->sta.regd_mc_addr_count); - - mc_filter_count = ndev_vif->sta.regd_mc_addr_count; - if (!mc_filter_count) - return 0; - - pkt_filter_elem = kmalloc((mc_filter_count * sizeof(struct slsi_mlme_pkt_filter_elem)), GFP_KERNEL); - if (!pkt_filter_elem) { - SLSI_NET_ERR(dev, "ERROR Memory allocation failure\n"); - return -ENOMEM; - } - - pattern_desc.offset = 0; - pattern_desc.mask_length = ETH_ALEN; - SLSI_ETHER_COPY(pattern_desc.mask, addr_mask); - - for (i = 0; i < mc_filter_count; i++) { - SLSI_ETHER_COPY(pattern_desc.pattern, ndev_vif->sta.regd_mc_addr[i]); - mc_filter_id = SLSI_REGD_MC_FILTER_ID + i; -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - if (sdev->enhanced_pkt_filter_enabled) - slsi_create_packet_filter_element(mc_filter_id, - FAPI_PACKETFILTERMODE_OPT_IN, - 1, &pattern_desc, - &pkt_filter_elem[num_filters], &pkt_filters_len); - else -#endif - slsi_create_packet_filter_element(mc_filter_id, - FAPI_PACKETFILTERMODE_OPT_IN | - FAPI_PACKETFILTERMODE_OPT_IN_SLEEP, - 1, &pattern_desc, - &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - } - - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); - kfree(pkt_filter_elem); - - return ret; -} - -int slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - - u8 i, pkt_filters_len = 0; - int num_filters = 0; - int ret = 0; - struct slsi_mlme_pkt_filter_elem *pkt_filter_elem; - u8 mc_filter_id; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION)) - return -EINVAL; - - if (WARN_ON(!peer)) - return -EINVAL; - - SLSI_NET_DBG2(dev, SLSI_MLME, "Clear filters on Screen on"); - - /*calculate number of filters*/ - num_filters = ndev_vif->sta.regd_mc_addr_count + SLSI_SCREEN_OFF_FILTERS_COUNT; - if ((slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) == false) { - num_filters++; - num_filters++; -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - num_filters++; -#endif - } - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - if (sdev->enhanced_pkt_filter_enabled) { - num_filters++; /*All OPT OUT*/ - num_filters++; /*TCP IPv4 OPT IN*/ - num_filters++; /*TCP IPv6 OPT IN*/ - } -#endif -#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER - if (sdev->abnormal_multicast_pkt_filter_enabled) - num_filters++;/* clear abnormal multicast packet */ -#endif - pkt_filter_elem = kmalloc((num_filters * sizeof(struct slsi_mlme_pkt_filter_elem)), GFP_KERNEL); - if (!pkt_filter_elem) { - SLSI_NET_ERR(dev, "ERROR Memory allocation failure"); - return -ENOMEM; - } - - num_filters = 0; - for (i = 0; i < ndev_vif->sta.regd_mc_addr_count; i++) { - mc_filter_id = SLSI_REGD_MC_FILTER_ID + i; - slsi_create_packet_filter_element(mc_filter_id, 0, 0, NULL, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - } - if ((slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) == false) { - slsi_create_packet_filter_element(SLSI_LOCAL_ARP_FILTER_ID, 0, 0, NULL, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - slsi_create_packet_filter_element(SLSI_ALL_ARP_FILTER_ID, 0, 0, NULL, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - slsi_create_packet_filter_element(SLSI_LOCAL_NS_FILTER_ID, 0, 0, NULL, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; -#endif - } - - slsi_create_packet_filter_element(SLSI_ALL_BC_MC_FILTER_ID, 0, 0, NULL, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - if (sdev->enhanced_pkt_filter_enabled) { - slsi_create_packet_filter_element(SLSI_OPT_OUT_ALL_FILTER_ID, 0, 0, NULL, - &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - slsi_create_packet_filter_element(SLSI_OPT_IN_TCP4_FILTER_ID, 0, 0, NULL, - &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - slsi_create_packet_filter_element(SLSI_OPT_IN_TCP6_FILTER_ID, 0, 0, NULL, - &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - } -#endif -#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER - if (sdev->abnormal_multicast_pkt_filter_enabled) { - slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, 0, 0, NULL, - &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - } -#endif - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); - kfree(pkt_filter_elem); - return ret; -} - -int slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev) -{ - int ret = 0; - - struct netdev_vif *ndev_vif = netdev_priv(dev); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION); - - ret = slsi_set_multicast_packet_filters(sdev, dev); - if (ret) - return ret; - - ret = slsi_set_arp_packet_filter(sdev, dev); - if (ret) - return ret; - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER - if (sdev->enhanced_pkt_filter_enabled) { - ret = slsi_set_opt_out_unicast_packet_filter(sdev, dev); - if (ret) - return ret; - ret = slsi_set_opt_in_tcp4_packet_filter(sdev, dev); - if (ret) - return ret; - ret = slsi_set_opt_in_tcp6_packet_filter(sdev, dev); - if (ret) - return ret; - } -#endif - /* install abnormal multicast packet filter */ -#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER - if (sdev->abnormal_multicast_pkt_filter_enabled) { - ret = slsi_set_opt_out_abnormal_multicast_packet_filter(sdev, dev); - if (ret) - return ret; - } -#endif - return slsi_set_common_packet_filters(sdev, dev); -} - -#define IPV6_PF_PATTERN_MASK 0xf0 -#define IPV6_PF_PATTERN 0x60 - -#ifdef CONFIG_SCSC_WLAN_DISABLE_NAT_KA -#define SLSI_ON_CONNECT_FILTERS_COUNT 2 -#else -#define SLSI_ON_CONNECT_FILTERS_COUNT 3 -#endif - -void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *dev) -{ - struct slsi_mlme_pattern_desc pattern_desc[SLSI_MAX_PATTERN_DESC]; - int num_pattern_desc = 0; - u8 pkt_filters_len = 0; - int num_filters = 0; - - struct slsi_mlme_pkt_filter_elem pkt_filter_elem[SLSI_ON_CONNECT_FILTERS_COUNT]; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - const u8 *ie; - - if (WARN_ON(!ndev_vif->activated)) - return; - - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION)) - return; - - if (WARN_ON(!peer)) - return; - - if (WARN_ON(!peer->assoc_resp_ie)) - return; - -#ifdef CONFIG_SCSC_WLAN_BLOCK_IPV6 - - /*Opt out all IPv6 packets in active and suspended mode (ipv6 filtering)*/ - num_pattern_desc = 0; - pattern_desc[num_pattern_desc].offset = 0x0E; /*filtering on IP Protocol version*/ - pattern_desc[num_pattern_desc].mask_length = 1; - pattern_desc[num_pattern_desc].mask[0] = IPV6_PF_PATTERN_MASK; - pattern_desc[num_pattern_desc].pattern[0] = IPV6_PF_PATTERN; - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_ALL_IPV6_PKTS_FILTER_ID, - FAPI_PACKETFILTERMODE_OPT_OUT | FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - -#endif - - ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, SLSI_WLAN_OUI_TYPE_WFA_HS20_IND, - ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len); - - if (ie) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Connected to HS2 AP "); - - if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Proxy ARP service supported on HS2 AP "); - - /* Opt out Gratuitous ARP packets (ARP Announcement) in active and suspended mode. - * For suspended mode, gratituous ARP is dropped by "opt out all broadcast" that will be - * set in slsi_set_common_packet_filters on screen off - */ - num_pattern_desc = 0; - pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/ - pattern_desc[num_pattern_desc].mask_length = ETH_ALEN; - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask); - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, addr_mask); - num_pattern_desc++; - - SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP); - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_PROXY_ARP_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - /* Opt out unsolicited Neighbor Advertisement packets .For suspended mode, NA is dropped by - * "opt out all IPv6 multicast" already set in slsi_create_common_packet_filters - */ - num_pattern_desc = 0; - - pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/ - pattern_desc[num_pattern_desc].mask_length = ETH_ALEN; - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask); - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask); - num_pattern_desc++; - - SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD); - num_pattern_desc++; - - pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/ - pattern_desc[num_pattern_desc].mask_length = 1; - pattern_desc[num_pattern_desc].mask[0] = 0xff; - pattern_desc[num_pattern_desc].pattern[0] = 0x3a; - num_pattern_desc++; - - pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/ - pattern_desc[num_pattern_desc].mask_length = 1; - pattern_desc[num_pattern_desc].mask[0] = 0xff; - pattern_desc[num_pattern_desc].pattern[0] = 0x88; /* Neighbor Advertisement type in ICMPv6 */ - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_PROXY_ARP_NA_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; -#endif - } - } - -#ifndef CONFIG_SCSC_WLAN_DISABLE_NAT_KA - { - const u8 nat_ka_pattern[4] = { 0x11, 0x94, 0x00, 0x09 }; - /*Opt out the NAT T for IPsec*/ - num_pattern_desc = 0; - pattern_desc[num_pattern_desc].offset = 0x24; /*filtering on destination port number*/ - pattern_desc[num_pattern_desc].mask_length = 4; - memcpy(pattern_desc[num_pattern_desc].mask, addr_mask, 4); - memcpy(pattern_desc[num_pattern_desc].pattern, nat_ka_pattern, 4); - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_NAT_IPSEC_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - } -#endif - - if (num_filters) - slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); -} - -int slsi_ip_address_changed(struct slsi_dev *sdev, struct net_device *dev, __be32 ipaddress) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int ret = 0; - - /* Store the IP address outside the check for vif being active - * as we get the same notification in case of static IP - */ - if (ndev_vif->ipaddress != ipaddress) - ndev_vif->ipaddress = ipaddress; - - if (ndev_vif->activated && (ndev_vif->vif_type == FAPI_VIFTYPE_AP)) { - struct slsi_mlme_pattern_desc pattern_desc[1]; - u8 num_patterns = 0; - struct slsi_mlme_pkt_filter_elem pkt_filter_elem[1]; - u8 pkt_filters_len = 0; - u8 num_filters = 0; - - ndev_vif->ipaddress = ipaddress; - ret = slsi_mlme_set_ip_address(sdev, dev); - if (ret != 0) - SLSI_NET_ERR(dev, "slsi_mlme_set_ip_address ERROR. ret=%d", ret); - - /* Opt out IPv6 packets in platform suspended mode */ - pattern_desc[num_patterns].offset = 0x0E; - pattern_desc[num_patterns].mask_length = 0x01; - pattern_desc[num_patterns].mask[0] = IPV6_PF_PATTERN_MASK; - pattern_desc[num_patterns++].pattern[0] = IPV6_PF_PATTERN; - - slsi_create_packet_filter_element(SLSI_AP_ALL_IPV6_PKTS_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP, - num_patterns, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); - num_filters++; - ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); - if (ret != 0) - SLSI_NET_ERR(dev, "slsi_mlme_set_packet_filter (return :%d) ERROR\n", ret); - } else if ((ndev_vif->activated) && - (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - - if (WARN_ON(!peer)) - return -EINVAL; - - if (!(peer->capabilities & WLAN_CAPABILITY_PRIVACY) || - (ndev_vif->sta.group_key_set && peer->pairwise_key_set)) - slsi_send_gratuitous_arp(sdev, dev); - else - ndev_vif->sta.gratuitous_arp_needed = true; - - slsi_mlme_powermgt(sdev, dev, ndev_vif->set_power_mode); - } - - return ret; -} - -#define SLSI_AP_AUTO_CHANLS_LIST_FROM_HOSTAPD_MAX 3 - -int slsi_auto_chan_select_scan(struct slsi_dev *sdev, int n_channels, struct ieee80211_channel *channels[]) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - struct sk_buff_head unique_scan_results; - int scan_result_count[SLSI_AP_AUTO_CHANLS_LIST_FROM_HOSTAPD_MAX] = { 0, 0, 0 }; - int i, j; - int r = 0; - int selected_index = 0; - int min_index = 0; - u32 freqdiff = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_WARN(sdev, "not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - - skb_queue_head_init(&unique_scan_results); - - dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); /* use the main VIF */ - if (!dev) { - r = -EINVAL; - return r; - } - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) { - r = -EBUSY; - goto exit_with_vif; - } - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = true; - r = slsi_mlme_add_scan(sdev, - dev, - FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION, - FAPI_REPORTMODE_REAL_TIME, - 0, /* n_ssids */ - NULL, /* ssids */ - n_channels, - channels, - NULL, - NULL, /* ie */ - 0, /* ie_len */ - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan); - - if (r == 0) { - struct sk_buff *unique_scan; - struct sk_buff *scan; - - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - while (scan) { - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(scan); - struct ieee80211_channel *channel; - - /* make sure this BSSID has not already been used */ - skb_queue_walk(&unique_scan_results, unique_scan) { - struct ieee80211_mgmt *unique_mgmt = fapi_get_mgmt(unique_scan); - - if (compare_ether_addr(mgmt->bssid, unique_mgmt->bssid) == 0) { - slsi_kfree_skb(scan); - goto next_scan; - } - } - - slsi_skb_queue_head(&unique_scan_results, scan); - - channel = slsi_find_scan_channel(sdev, mgmt, fapi_get_mgmtlen(scan), fapi_get_u16(scan, u.mlme_scan_ind.channel_frequency) / 2); - if (!channel) - goto next_scan; - - /* check for interfering channels for 1, 6 and 11 */ - for (i = 0, j = 0; i < SLSI_AP_AUTO_CHANLS_LIST_FROM_HOSTAPD_MAX && channels[j]; i++, j = j + 5) { - if (channel->center_freq == channels[j]->center_freq) { - SLSI_NET_DBG3(dev, SLSI_CFG80211, "exact match:%d\n", i); - scan_result_count[i] += 5; - goto next_scan; - } - freqdiff = abs((int)channel->center_freq - (channels[j]->center_freq)); - if (freqdiff <= 20) { - SLSI_NET_DBG3(dev, SLSI_CFG80211, "overlapping:%d, freqdiff:%d\n", i, freqdiff); - scan_result_count[i] += (5 - (freqdiff / 5)); - } - } - -next_scan: - scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - - /* Select the channel to use */ - for (i = 0, j = 0; i < SLSI_AP_AUTO_CHANLS_LIST_FROM_HOSTAPD_MAX; i++, j = j + 5) { - SLSI_NET_DBG3(dev, SLSI_CFG80211, "score[%d]:%d\n", i, scan_result_count[i]); - if (scan_result_count[i] <= scan_result_count[min_index]) { - min_index = i; - selected_index = j; - } - } - SLSI_NET_DBG3(dev, SLSI_CFG80211, "selected:%d with score:%d\n", selected_index, scan_result_count[min_index]); - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - sdev->device_config.ap_auto_chan = channels[selected_index]->hw_value & 0xFF; - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - SLSI_INFO(sdev, "Channel selected = %d", sdev->device_config.ap_auto_chan); - } - slsi_skb_queue_purge(&unique_scan_results); - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = false; - -exit_with_vif: - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return r; -} - -int slsi_set_boost(struct slsi_dev *sdev, struct net_device *dev) -{ - int error = 0; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - error = slsi_set_mib_rssi_boost(sdev, dev, SLSI_PSID_UNIFI_ROAM_RSSI_BOOST, 1, - sdev->device_config.rssi_boost_2g); - if (error) - SLSI_ERR(sdev, "Err setting boost value For 2g after adding vif. error = %d\n", error); - error = slsi_set_mib_rssi_boost(sdev, dev, SLSI_PSID_UNIFI_ROAM_RSSI_BOOST, 2, - sdev->device_config.rssi_boost_5g); - if (error) - SLSI_ERR(sdev, "Err setting boost value for 5g after adding vif . error = %d\n", error); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return error; -} - -/** - * Work to be done when ROC retention duration expires: - * Send ROC expired event to cfg80211 and queue work to delete unsync vif after retention timeout. - */ -static void slsi_p2p_roc_duration_expiry_work(struct work_struct *work) -{ - struct netdev_vif *ndev_vif = container_of((struct delayed_work *)work, struct netdev_vif, unsync.roc_expiry_work); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - /* There can be a race condition of this work function waiting for ndev_vif->vif_mutex and meanwhile the vif is deleted (due to net_stop). - * In such cases ndev_vif->chan would have been cleared. - */ - if (ndev_vif->sdev->p2p_state == P2P_IDLE_NO_VIF) { - SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_CFG80211, "P2P unsync vif is not present\n"); - goto exit; - } - - SLSI_NET_DBG3(ndev_vif->wdev.netdev, SLSI_CFG80211, "Send ROC expired event\n"); - - /* If action frame tx is in progress don't schedule work to delete vif */ - if (ndev_vif->sdev->p2p_state != P2P_ACTION_FRAME_TX_RX) { - /* After sucessful frame transmission, we will move to LISTENING or VIF ACTIVE state. - * Unset channel should not be sent down during p2p procedure. - */ - if (!ndev_vif->drv_in_p2p_procedure) { - if (delayed_work_pending(&ndev_vif->unsync.unset_channel_expiry_work)) - cancel_delayed_work(&ndev_vif->unsync.unset_channel_expiry_work); - queue_delayed_work(ndev_vif->sdev->device_wq, &ndev_vif->unsync.unset_channel_expiry_work, - msecs_to_jiffies(SLSI_P2P_UNSET_CHANNEL_EXTRA_MSEC)); - } - slsi_p2p_queue_unsync_vif_del_work(ndev_vif, SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC); - SLSI_P2P_STATE_CHANGE(ndev_vif->sdev, P2P_IDLE_VIF_ACTIVE); - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_remain_on_channel_expired(&ndev_vif->wdev, ndev_vif->unsync.roc_cookie, ndev_vif->chan, GFP_KERNEL); -#else - cfg80211_remain_on_channel_expired(ndev_vif->wdev.netdev, ndev_vif->unsync.roc_cookie, - ndev_vif->chan, ndev_vif->channel_type, GFP_KERNEL); -#endif - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -/** - * Work to be done when unsync vif retention duration expires: - * Delete the unsync vif. - */ -static void slsi_p2p_unsync_vif_delete_work(struct work_struct *work) -{ - struct netdev_vif *ndev_vif = container_of((struct delayed_work *)work, struct netdev_vif, unsync.del_vif_work); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_CFG80211, "Delete vif duration expired - Deactivate unsync vif\n"); - slsi_p2p_vif_deactivate(ndev_vif->sdev, ndev_vif->wdev.netdev, true); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -/** - * Work to be done after roc expiry or cancel remain on channel: - * Unset channel to be sent to Fw. - */ -static void slsi_p2p_unset_channel_expiry_work(struct work_struct *work) -{ - struct netdev_vif *ndev_vif = container_of((struct delayed_work *)work, struct netdev_vif, - unsync.unset_channel_expiry_work); - struct slsi_dev *sdev = ndev_vif->sdev; - struct net_device *dev = ndev_vif->wdev.netdev; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->activated) { - SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_CFG80211, "Unset channel expiry work-Send Unset Channel\n"); - if (!ndev_vif->drv_in_p2p_procedure) { - /* Supplicant has stopped FIND/LISTEN. Clear Probe Response IEs in firmware and driver */ - if (slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_RESPONSE, NULL, 0) != 0) - SLSI_NET_ERR(dev, "Clearing Probe Response IEs failed for unsync vif\n"); - slsi_unsync_vif_set_probe_rsp_ie(ndev_vif, NULL, 0); - - /* Send Unset Channel */ - if (ndev_vif->driver_channel != 0) { - slsi_mlme_unset_channel_req(sdev, dev); - ndev_vif->driver_channel = 0; - } - } - } else { - SLSI_NET_ERR(dev, "P2P vif is not activated\n"); - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -/* Initializations for P2P - Change vif type to unsync, create workqueue and init work */ -int slsi_p2p_init(struct slsi_dev *sdev, struct netdev_vif *ndev_vif) -{ - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "Initialize P2P - Init P2P state to P2P_IDLE_NO_VIF\n"); - sdev->p2p_state = P2P_IDLE_NO_VIF; - sdev->p2p_group_exp_frame = SLSI_P2P_PA_INVALID; - - ndev_vif->vif_type = FAPI_VIFTYPE_UNSYNCHRONISED; - ndev_vif->unsync.slsi_p2p_continuous_fullscan = false; - - - INIT_DELAYED_WORK(&ndev_vif->unsync.roc_expiry_work, slsi_p2p_roc_duration_expiry_work); - INIT_DELAYED_WORK(&ndev_vif->unsync.del_vif_work, slsi_p2p_unsync_vif_delete_work); - INIT_DELAYED_WORK(&ndev_vif->unsync.unset_channel_expiry_work, slsi_p2p_unset_channel_expiry_work); - return 0; -} - -/* De-initializations for P2P - Reset vif type, cancel work and destroy workqueue */ -void slsi_p2p_deinit(struct slsi_dev *sdev, struct netdev_vif *ndev_vif) -{ - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "De-initialize P2P\n"); - - ndev_vif->vif_type = SLSI_VIFTYPE_UNSPECIFIED; - - /* Work should have been cleaned up by now */ - if (WARN_ON(delayed_work_pending(&ndev_vif->unsync.del_vif_work))) - cancel_delayed_work(&ndev_vif->unsync.del_vif_work); - - if (WARN_ON(delayed_work_pending(&ndev_vif->unsync.roc_expiry_work))) - cancel_delayed_work(&ndev_vif->unsync.roc_expiry_work); -} - -/** - * P2P vif activation: - * Add unsync vif, register for action frames, configure Probe Rsp IEs if required and set channel - */ -int slsi_p2p_vif_activate(struct slsi_dev *sdev, struct net_device *dev, struct ieee80211_channel *chan, u16 duration, bool set_probe_rsp_ies) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u32 af_bmap_active = SLSI_ACTION_FRAME_PUBLIC; - u32 af_bmap_suspended = SLSI_ACTION_FRAME_PUBLIC; - int r = 0; - - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "Activate P2P unsync vif\n"); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - /* Interface address and device address are same for P2P unsync vif */ - if (slsi_mlme_add_vif(sdev, dev, dev->dev_addr, dev->dev_addr) != 0) { - SLSI_NET_ERR(dev, "slsi_mlme_add_vif failed for unsync vif\n"); - goto exit_with_error; - } - - ndev_vif->activated = true; - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE); - - if (slsi_mlme_register_action_frame(sdev, dev, af_bmap_active, af_bmap_suspended) != 0) { - SLSI_NET_ERR(dev, "Action frame registration failed for unsync vif\n"); - goto exit_with_vif; - } - - if (set_probe_rsp_ies) { - u16 purpose = FAPI_PURPOSE_PROBE_RESPONSE; - - if (!ndev_vif->unsync.probe_rsp_ies) { - SLSI_NET_ERR(dev, "Probe Response IEs not available for ROC\n"); - goto exit_with_vif; - } - - if (slsi_mlme_add_info_elements(sdev, dev, purpose, ndev_vif->unsync.probe_rsp_ies, ndev_vif->unsync.probe_rsp_ies_len) != 0) { - SLSI_NET_ERR(dev, "Setting Probe Response IEs for unsync vif failed\n"); - goto exit_with_vif; - } - ndev_vif->unsync.ies_changed = false; - } - - if (slsi_mlme_set_channel(sdev, dev, chan, SLSI_FW_CHANNEL_DURATION_UNSPECIFIED, 0, 0) != 0) { - SLSI_NET_ERR(dev, "Set channel failed for unsync vif\n"); - goto exit_with_vif; - } else { - ndev_vif->chan = chan; - ndev_vif->driver_channel = chan->hw_value; - } - - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - goto exit; - -exit_with_vif: - slsi_p2p_vif_deactivate(sdev, dev, true); -exit_with_error: - r = -EINVAL; -exit: - return r; -} - -/* Delete unsync vif - DON'T update the vif type */ -void slsi_p2p_vif_deactivate(struct slsi_dev *sdev, struct net_device *dev, bool hw_available) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "De-activate P2P unsync vif\n"); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (sdev->p2p_state == P2P_IDLE_NO_VIF) { - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "P2P unsync vif already deactivated\n"); - return; - } - - /* Indicate failure using cfg80211_mgmt_tx_status() if frame TX is not completed during VIF delete */ - if (ndev_vif->mgmt_tx_data.exp_frame != SLSI_P2P_PA_INVALID) { - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) - cfg80211_mgmt_tx_status(&ndev_vif->wdev, ndev_vif->mgmt_tx_data.cookie, ndev_vif->mgmt_tx_data.buf, ndev_vif->mgmt_tx_data.buf_len, false, GFP_KERNEL); -#else - cfg80211_mgmt_tx_status(dev, ndev_vif->mgmt_tx_data.cookie, ndev_vif->mgmt_tx_data.buf, ndev_vif->mgmt_tx_data.buf_len, false, GFP_KERNEL); -#endif - } - - cancel_delayed_work(&ndev_vif->unsync.del_vif_work); - cancel_delayed_work(&ndev_vif->unsync.roc_expiry_work); - - if (hw_available) - slsi_mlme_del_vif(sdev, dev); - - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_NO_VIF); - - /* slsi_vif_deactivated is not used here after del_vif as it modifies vif type as well */ - - ndev_vif->activated = false; - ndev_vif->chan = NULL; - - if (WARN_ON(ndev_vif->unsync.listen_offload)) - ndev_vif->unsync.listen_offload = false; - - slsi_unsync_vif_set_probe_rsp_ie(ndev_vif, NULL, 0); - (void)slsi_set_mgmt_tx_data(ndev_vif, 0, 0, NULL, 0); - - SLSI_NET_DBG2(dev, SLSI_INIT_DEINIT, "P2P unsync vif deactivated\n"); -} - -/** - * Delete unsync vif when group role is being started. - * For such cases the net_device during the call would be of the group interface (called from ap_start/connect). - * Hence get the net_device using P2P Index. Take the mutex lock and call slsi_p2p_vif_deactivate. - */ -void slsi_p2p_group_start_remove_unsync_vif(struct slsi_dev *sdev) -{ - struct net_device *dev = NULL; - struct netdev_vif *ndev_vif = NULL; - - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "Starting P2P Group - Remove unsync vif\n"); - - dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2P); - if (!dev) { - SLSI_ERR(sdev, "Failed to deactivate p2p vif as dev is not found\n"); - return; - } - - ndev_vif = netdev_priv(dev); - - if (WARN_ON(!(SLSI_IS_P2P_UNSYNC_VIF(ndev_vif)))) - return; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - slsi_p2p_vif_deactivate(sdev, dev, true); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -/** - * Called only for P2P Device mode (p2p0 interface) to store the Probe Response IEs - * which would be used in Listen (ROC) state. - * If the IEs are received in Listen Offload mode, then configure the IEs in firmware. - */ -int slsi_p2p_dev_probe_rsp_ie(struct slsi_dev *sdev, struct net_device *dev, u8 *probe_rsp_ie, size_t probe_rsp_ie_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int ret = 0; - - SLSI_UNUSED_PARAMETER(sdev); - - if (!SLSI_IS_P2P_UNSYNC_VIF(ndev_vif)) { - SLSI_NET_ERR(dev, "Incorrect vif type - Not unsync vif\n"); - kfree(probe_rsp_ie); - return -EINVAL; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Received Probe Rsp IE len = %zu, Current IE len = %zu\n", probe_rsp_ie_len, ndev_vif->unsync.probe_rsp_ies_len); - - if (!ndev_vif->unsync.listen_offload) { /* ROC */ - /* Store the IEs. Upon receiving it on subsequent occassions, store only if IEs have changed */ - if (ndev_vif->unsync.probe_rsp_ies_len != probe_rsp_ie_len) /* Check if IE length changed */ - ndev_vif->unsync.ies_changed = true; - else if (memcmp(ndev_vif->unsync.probe_rsp_ies, probe_rsp_ie, probe_rsp_ie_len) != 0) /* Check if IEs changed */ - ndev_vif->unsync.ies_changed = true; - else { /* No change in IEs */ - kfree(probe_rsp_ie); - goto exit; - } - - slsi_unsync_vif_set_probe_rsp_ie(ndev_vif, probe_rsp_ie, probe_rsp_ie_len); - } else { /* P2P Listen Offloading */ - if (sdev->p2p_state == P2P_LISTENING) { - ret = slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_RESPONSE, probe_rsp_ie, probe_rsp_ie_len); - if (ret != 0) { - SLSI_NET_ERR(dev, "Listen Offloading: Setting Probe Response IEs for unsync vif failed\n"); - ndev_vif->unsync.listen_offload = false; - slsi_p2p_vif_deactivate(sdev, dev, true); - } - } - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return ret; -} - -/** - * This should be called only for P2P Device mode (p2p0 interface). NULL IEs to clear Probe Response IEs are not updated - * in driver to avoid configuring the Probe Response IEs to firmware on every ROC. - * Use this call as a cue to stop any ongoing P2P scan as there is no API from user space for cancelling scan. - * If ROC was in progress as part of P2P_FIND then Cancel ROC will be received. - */ -int slsi_p2p_dev_null_ies(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct cfg80211_scan_info info = {.aborted = true}; - - if (!SLSI_IS_P2P_UNSYNC_VIF(ndev_vif)) { - SLSI_NET_ERR(dev, "Incorrect vif type - Not unsync vif\n"); - return -EINVAL; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG3(dev, SLSI_CFG80211, "Probe Rsp NULL IEs\n"); - - if (sdev->p2p_state == P2P_SCANNING) { - struct sk_buff *scan_result; - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Stop Find - Abort ongoing P2P scan\n"); - - (void)slsi_mlme_del_scan(sdev, dev, ((ndev_vif->ifnum << 8) | SLSI_SCAN_HW_ID), false); - - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - scan_result = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - while (scan_result) { - slsi_rx_scan_pass_to_cfg80211(sdev, dev, scan_result); - scan_result = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - - WARN_ON(!ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req); - - if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, &info); -#else - cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, true); -#endif - - ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req = NULL; - - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - - if (ndev_vif->activated) { - /* Supplicant has stopped FIND. Also clear Probe Response IEs in firmware and driver - * as Cancel ROC will not be sent as driver was not in Listen - */ - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Stop Find - Clear Probe Response IEs in firmware\n"); - if (slsi_mlme_add_info_elements(sdev, dev, FAPI_PURPOSE_PROBE_RESPONSE, NULL, 0) != 0) - SLSI_NET_ERR(dev, "Clearing Probe Response IEs failed for unsync vif\n"); - slsi_unsync_vif_set_probe_rsp_ie(ndev_vif, NULL, 0); - - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE); - } else { - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_NO_VIF); - } - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return 0; -} - -/** - * Returns the P2P public action frame subtype. - * Returns SLSI_P2P_PA_INVALID if it is not a P2P public action frame. - */ -int slsi_p2p_get_public_action_subtype(const struct ieee80211_mgmt *mgmt) -{ - int subtype = SLSI_P2P_PA_INVALID; - /* Vendor specific Public Action (0x09), P2P OUI (0x50, 0x6f, 0x9a), P2P Subtype (0x09) */ - u8 p2p_pa_frame[5] = { 0x09, 0x50, 0x6f, 0x9a, 0x09 }; - u8 *action = (u8 *)&mgmt->u.action.u; - - if (memcmp(&action[0], p2p_pa_frame, 5) == 0) { - subtype = action[5]; - } else { - /* For service discovery action frames dummy subtype is used */ - switch (action[0]) { - case SLSI_PA_GAS_INITIAL_REQ: - case SLSI_PA_GAS_INITIAL_RSP: - case SLSI_PA_GAS_COMEBACK_REQ: - case SLSI_PA_GAS_COMEBACK_RSP: - subtype = (action[0] | SLSI_PA_GAS_DUMMY_SUBTYPE_MASK); - break; - } - } - - return subtype; -} - -/** - * Returns the P2P status code of Status attribute of the GO Neg Rsp frame. - * Returns -1 if status attribute is NOT found. - */ -int slsi_p2p_get_go_neg_rsp_status(struct net_device *dev, const struct ieee80211_mgmt *mgmt) -{ - int status = -1; - u8 p2p_oui_type[4] = { 0x50, 0x6f, 0x9a, 0x09 }; - u8 *action = (u8 *)&mgmt->u.action.u; - u8 *vendor_ie = &action[7]; /* 1 (0x09), 4 (0x50, 0x6f, 0x9a, 0x09), 1 (0x01), 1 (Dialog Token) */ - u8 ie_length, elem_idx; - u16 attr_length; - - while (vendor_ie && (*vendor_ie == SLSI_WLAN_EID_VENDOR_SPECIFIC)) { - ie_length = vendor_ie[1]; - - if (memcmp(&vendor_ie[2], p2p_oui_type, 4) == 0) { - elem_idx = 6; /* 1 (Id - 0xdd) + 1 (Length) + 4 (OUI and Type) */ - - while (ie_length > elem_idx) { - attr_length = ((vendor_ie[elem_idx + 1]) | (vendor_ie[elem_idx + 2] << 8)); - - if (vendor_ie[elem_idx] == SLSI_P2P_STATUS_ATTR_ID) { - SLSI_NET_DBG3(dev, SLSI_CFG80211, "Status Attribute Found, attr_length = %d, value (%u %u %u %u)\n", - attr_length, vendor_ie[elem_idx], vendor_ie[elem_idx + 1], vendor_ie[elem_idx + 2], vendor_ie[elem_idx + 3]); - status = vendor_ie[elem_idx + 3]; - break; - } - elem_idx += 3 + attr_length; - } - - break; - } - vendor_ie += 2 + ie_length; - } - - SLSI_UNUSED_PARAMETER(dev); - - return status; -} - -/** - * Returns the next expected P2P public action frame subtype for input subtype. - * Returns SLSI_P2P_PA_INVALID if no frame is expected. - */ -u8 slsi_p2p_get_exp_peer_frame_subtype(u8 subtype) -{ - switch (subtype) { - /* Peer response is expected for following frames */ - case SLSI_P2P_PA_GO_NEG_REQ: - case SLSI_P2P_PA_GO_NEG_RSP: - case SLSI_P2P_PA_INV_REQ: - case SLSI_P2P_PA_DEV_DISC_REQ: - case SLSI_P2P_PA_PROV_DISC_REQ: - case SLSI_PA_GAS_INITIAL_REQ_SUBTYPE: - case SLSI_PA_GAS_COMEBACK_REQ_SUBTYPE: - return subtype + 1; - default: - return SLSI_P2P_PA_INVALID; - } -} - -void slsi_wlan_dump_public_action_subtype(struct slsi_dev *sdev, struct ieee80211_mgmt *mgmt, bool tx) -{ - u8 action_code = ((u8 *)&mgmt->u.action.u)[0]; - u8 action_category = mgmt->u.action.category; - char *tx_rx_string = "Received"; - char wnm_action_fields[28][35] = { "Event Request", "Event Report", "Diagnostic Request", - "Diagnostic Report", "Location Configuration Request", - "Location Configuration Response", "BSS Transition Management Query", - "BSS Transition Management Request", - "BSS Transition Management Response", "FMS Request", "FMS Response", - "Collocated Interference Request", "Collocated Interference Report", - "TFS Request", "TFS Response", "TFS Notify", "WNM Sleep Mode Request", - "WNM Sleep Mode Response", "TIM Broadcast Request", - "TIM Broadcast Response", "QoS Traffic Capability Update", - "Channel Usage Request", "Channel Usage Response", "DMS Request", - "DMS Response", "Timing Measurement Request", - "WNM Notification Request", "WNM Notification Response" }; - - if (tx) - tx_rx_string = "Send"; - - switch (action_category) { - case WLAN_CATEGORY_RADIO_MEASUREMENT: - switch (action_code) { - case SLSI_RM_RADIO_MEASUREMENT_REQ: - SLSI_INFO(sdev, "%s Radio Measurement Frame (Radio Measurement Req)\n", tx_rx_string); - break; - case SLSI_RM_RADIO_MEASUREMENT_REP: - SLSI_INFO(sdev, "%s Radio Measurement Frame (Radio Measurement Rep)\n", tx_rx_string); - break; - case SLSI_RM_LINK_MEASUREMENT_REQ: - SLSI_INFO(sdev, "%s Radio Measurement Frame (Link Measurement Req)\n", tx_rx_string); - break; - case SLSI_RM_LINK_MEASUREMENT_REP: - SLSI_INFO(sdev, "%s Radio Measurement Frame (Link Measurement Rep)\n", tx_rx_string); - break; - case SLSI_RM_NEIGH_REP_REQ: - SLSI_INFO(sdev, "%s Radio Measurement Frame (Neighbor Report Req)\n", tx_rx_string); - break; - case SLSI_RM_NEIGH_REP_RSP: - SLSI_INFO(sdev, "%s Radio Measurement Frame (Neighbor Report Resp)\n", tx_rx_string); - break; - default: - SLSI_INFO(sdev, "%s Radio Measurement Frame (Reserved)\n", tx_rx_string); - } - break; - case WLAN_CATEGORY_PUBLIC: - switch (action_code) { - case SLSI_PA_GAS_INITIAL_REQ: - SLSI_DBG1_NODEV(SLSI_CFG80211, "%s: GAS Initial Request\n", tx ? "TX" : "RX"); - break; - case SLSI_PA_GAS_INITIAL_RSP: - SLSI_DBG1_NODEV(SLSI_CFG80211, "%s: GAS Initial Response\n", tx ? "TX" : "RX"); - break; - case SLSI_PA_GAS_COMEBACK_REQ: - SLSI_DBG1_NODEV(SLSI_CFG80211, "%s: GAS Comeback Request\n", tx ? "TX" : "RX"); - break; - case SLSI_PA_GAS_COMEBACK_RSP: - SLSI_DBG1_NODEV(SLSI_CFG80211, "%s: GAS Comeback Response\n", tx ? "TX" : "RX"); - break; - default: - SLSI_DBG1_NODEV(SLSI_CFG80211, "Unknown GAS Frame : %d\n", action_code); - } - break; - case WLAN_CATEGORY_WNM: - if (action_code >= SLSI_WNM_ACTION_FIELD_MIN && action_code <= SLSI_WNM_ACTION_FIELD_MAX) - SLSI_INFO(sdev, "%s WNM Frame (%s)\n", tx_rx_string, wnm_action_fields[action_code]); - else - SLSI_INFO(sdev, "%s WNM Frame (Reserved)\n", tx_rx_string); - break; - } -} - -void slsi_abort_sta_scan(struct slsi_dev *sdev) -{ - struct net_device *wlan_net_dev = NULL; - struct netdev_vif *ndev_vif; - struct cfg80211_scan_info info = {.aborted = true}; - - wlan_net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - - if (!wlan_net_dev) { - SLSI_ERR(sdev, "Dev not found\n"); - return; - } - - ndev_vif = netdev_priv(wlan_net_dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) { - struct sk_buff *scan_result; - - SLSI_DBG2(sdev, SLSI_CFG80211, "Abort ongoing WLAN scan\n"); - (void)slsi_mlme_del_scan(sdev, wlan_net_dev, ((ndev_vif->ifnum << 8) | SLSI_SCAN_HW_ID), false); - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - scan_result = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - while (scan_result) { - slsi_rx_scan_pass_to_cfg80211(sdev, wlan_net_dev, scan_result); - scan_result = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, &info); -#else - cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, true); -#endif - - ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req = NULL; - ndev_vif->scan[SLSI_SCAN_HW_ID].requeue_timeout_work = false; - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -/** - * Returns a slsi_dhcp_tx enum value after verifying whether the 802.11 packet in skb - * is a DHCP packet (identified by UDP port numbers) - */ -int slsi_is_dhcp_packet(u8 *data) -{ - u8 *p; - int ret = SLSI_TX_IS_NOT_DHCP; - - p = data + SLSI_IP_TYPE_OFFSET; - - if (*p == SLSI_IP_TYPE_UDP) { - u16 source_port, dest_port; - - p = data + SLSI_IP_SOURCE_PORT_OFFSET; - source_port = p[0] << 8 | p[1]; - p = data + SLSI_IP_DEST_PORT_OFFSET; - dest_port = p[0] << 8 | p[1]; - if ((source_port == SLSI_DHCP_CLIENT_PORT) && (dest_port == SLSI_DHCP_SERVER_PORT)) - ret = SLSI_TX_IS_DHCP_CLIENT; - else if ((source_port == SLSI_DHCP_SERVER_PORT) && (dest_port == SLSI_DHCP_CLIENT_PORT)) - ret = SLSI_TX_IS_DHCP_SERVER; - } - - return ret; -} - -#ifdef CONFIG_SCSC_WLAN_PRIORITISE_IMP_FRAMES -int slsi_is_tcp_sync_packet(struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - /* for AP type (AP or P2P Go) check if the packet is local or intra BSS. If intra BSS then - * the IP header and TCP header are not set; so return 0 - */ - if ((ndev_vif->vif_type == FAPI_VIFTYPE_AP) && (compare_ether_addr(eth_hdr(skb)->h_source, dev->dev_addr) != 0)) - return 0; - if (be16_to_cpu(eth_hdr(skb)->h_proto) != ETH_P_IP) - return 0; - if (ip_hdr(skb)->protocol != IPPROTO_TCP) - return 0; - if (!skb_transport_header_was_set(skb)) - return 0; - if (tcp_hdr(skb)->syn) - return 1; - - return 0; -} - -int slsi_is_dns_packet(u8 *data) -{ - u8 *p; - - p = data + SLSI_IP_TYPE_OFFSET; - - if (*p == SLSI_IP_TYPE_UDP) { - u16 dest_port; - - p = data + SLSI_IP_DEST_PORT_OFFSET; - dest_port = p[0] << 8 | p[1]; - if (dest_port == SLSI_DNS_DEST_PORT) /* 0x0035 */ - return 1; - } - - return 0; -} - -int slsi_is_mdns_packet(u8 *data) -{ - u8 *p; - - p = data + SLSI_IP_TYPE_OFFSET; - - if (*p == SLSI_IP_TYPE_UDP) { - u16 dest_port; - - p = data + SLSI_IP_DEST_PORT_OFFSET; - dest_port = p[0] << 8 | p[1]; - if (dest_port == SLSI_MDNS_DEST_PORT) - return 1; - } - return 0; -} -#endif - -int slsi_ap_prepare_add_info_ies(struct netdev_vif *ndev_vif, const u8 *ies, size_t ies_len) -{ - const u8 *wps_p2p_ies = NULL; - size_t wps_p2p_ie_len = 0; - - /* The ies may contain Extended Capability followed by WPS IE. The Extended capability IE needs to be excluded. */ - wps_p2p_ies = cfg80211_find_ie(SLSI_WLAN_EID_VENDOR_SPECIFIC, ies, ies_len); - if (wps_p2p_ies) { - size_t temp_len = wps_p2p_ies - ies; - - wps_p2p_ie_len = ies_len - temp_len; - } - - SLSI_NET_DBG2(ndev_vif->wdev.netdev, SLSI_MLME, "WPA IE len = %zu, WMM IE len = %zu, IEs len = %zu, WPS_P2P IEs len = %zu\n", - ndev_vif->ap.wpa_ie_len, ndev_vif->ap.wmm_ie_len, ies_len, wps_p2p_ie_len); - - ndev_vif->ap.add_info_ies_len = ndev_vif->ap.wpa_ie_len + ndev_vif->ap.wmm_ie_len + wps_p2p_ie_len; - ndev_vif->ap.add_info_ies = kmalloc(ndev_vif->ap.add_info_ies_len, GFP_KERNEL); /* Caller needs to free this */ - - if (!ndev_vif->ap.add_info_ies) { - SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_MLME, "Failed to allocate memory for IEs\n"); - ndev_vif->ap.add_info_ies_len = 0; - return -ENOMEM; - } - - if (ndev_vif->ap.cache_wpa_ie) { - memcpy(ndev_vif->ap.add_info_ies, ndev_vif->ap.cache_wpa_ie, ndev_vif->ap.wpa_ie_len); - ndev_vif->ap.add_info_ies += ndev_vif->ap.wpa_ie_len; - } - - if (ndev_vif->ap.cache_wmm_ie) { - memcpy(ndev_vif->ap.add_info_ies, ndev_vif->ap.cache_wmm_ie, ndev_vif->ap.wmm_ie_len); - ndev_vif->ap.add_info_ies += ndev_vif->ap.wmm_ie_len; - } - - if (wps_p2p_ies) { - memcpy(ndev_vif->ap.add_info_ies, wps_p2p_ies, wps_p2p_ie_len); - ndev_vif->ap.add_info_ies += wps_p2p_ie_len; - } - - ndev_vif->ap.add_info_ies -= ndev_vif->ap.add_info_ies_len; - - return 0; -} - -/* Set the correct bit in the channel sets */ -static void slsi_roam_channel_cache_add_channel(struct slsi_roaming_network_map_entry *network_map, u8 channel) -{ - if (channel <= 14) - network_map->channels_24_ghz |= (1 << channel); - else if (channel >= 36 && channel <= 64) /* Uni1 */ - network_map->channels_5_ghz |= (1 << ((channel - 36) / 4)); - else if (channel >= 100 && channel <= 140) /* Uni2 */ - network_map->channels_5_ghz |= (1 << (8 + ((channel - 100) / 4))); - else if (channel >= 149 && channel <= 165) /* Uni3 */ - network_map->channels_5_ghz |= (1 << (24 + ((channel - 149) / 4))); -} - -void slsi_roam_channel_cache_add_entry(struct slsi_dev *sdev, struct net_device *dev, const u8 *ssid, const u8 *bssid, u8 channel) -{ - struct list_head *pos; - int found = 0; - struct netdev_vif *ndev_vif = netdev_priv(dev); - - list_for_each(pos, &ndev_vif->sta.network_map) { - struct slsi_roaming_network_map_entry *network_map = list_entry(pos, struct slsi_roaming_network_map_entry, list); - - if (network_map->ssid.ssid_len == ssid[1] && - memcmp(network_map->ssid.ssid, &ssid[2], ssid[1]) == 0) { - found = 1; - network_map->last_seen_jiffies = jiffies; - if (network_map->only_one_ap_seen && memcmp(network_map->initial_bssid, bssid, ETH_ALEN) != 0) - network_map->only_one_ap_seen = false; - slsi_roam_channel_cache_add_channel(network_map, channel); - break; - } - } - if (!found) { - struct slsi_roaming_network_map_entry *network_map; - - SLSI_NET_DBG3(dev, SLSI_MLME, "New Entry : Channel: %d : %.*s\n", channel, ssid[1], &ssid[2]); - network_map = kmalloc(sizeof(*network_map), GFP_ATOMIC); - if (network_map) { - network_map->ssid.ssid_len = ssid[1]; - memcpy(network_map->ssid.ssid, &ssid[2], ssid[1]); - network_map->channels_24_ghz = 0; - network_map->channels_5_ghz = 0; - network_map->last_seen_jiffies = jiffies; - SLSI_ETHER_COPY(network_map->initial_bssid, bssid); - network_map->only_one_ap_seen = true; - slsi_roam_channel_cache_add_channel(network_map, channel); - list_add(&network_map->list, &ndev_vif->sta.network_map); - } else { - SLSI_ERR(sdev, "New Entry : %.*s kmalloc() failed\n", ssid[1], &ssid[2]); - } - } -} - -void slsi_roam_channel_cache_add(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - size_t mgmt_len = fapi_get_mgmtlen(skb); - int ielen = mgmt_len - (mgmt->u.beacon.variable - (u8 *)mgmt); - u32 freq = fapi_get_u16(skb, u.mlme_scan_ind.channel_frequency) / 2; - const u8 *scan_ds = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, ielen); - const u8 *scan_ht = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable, ielen); - const u8 *scan_ssid = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, ielen); - u8 chan = 0; - - /* Use the DS or HT channel as the Offchannel results mean the RX freq is not reliable */ - if (scan_ds) - chan = scan_ds[2]; - else if (scan_ht) - chan = scan_ht[2]; - else - chan = ieee80211_frequency_to_channel(freq); - - if (chan) { - enum nl80211_band band = NL80211_BAND_2GHZ; - - if (chan > 14) - band = NL80211_BAND_5GHZ; - -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (freq != (u32)ieee80211_channel_to_frequency(chan, band)) { - if (band == NL80211_BAND_5GHZ && freq < 3000) - SLSI_NET_DBG2(dev, SLSI_MLME, "Off Band Result : mlme_scan_ind(freq:%d) != DS(freq:%d)\n", freq, ieee80211_channel_to_frequency(chan, band)); - - if (band == NL80211_BAND_2GHZ && freq > 3000) - SLSI_NET_DBG2(dev, SLSI_MLME, "Off Band Result : mlme_scan_ind(freq:%d) != DS(freq:%d)\n", freq, ieee80211_channel_to_frequency(chan, band)); - } -#endif - } - - if (!scan_ssid || !scan_ssid[1] || scan_ssid[1] > 32) { - SLSI_NET_DBG3(dev, SLSI_MLME, "SSID not defined : Could not find SSID ie or Hidden\n"); - return; - } - - slsi_roam_channel_cache_add_entry(sdev, dev, scan_ssid, mgmt->bssid, chan); -} - -void slsi_roam_channel_cache_prune(struct net_device *dev, int seconds) -{ - struct slsi_roaming_network_map_entry *network_map; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct list_head *pos, *q; - unsigned long now = jiffies; - unsigned long age; - - list_for_each_safe(pos, q, &ndev_vif->sta.network_map) { - network_map = list_entry(pos, struct slsi_roaming_network_map_entry, list); - age = (now - network_map->last_seen_jiffies) / HZ; - - if (time_after_eq(now, network_map->last_seen_jiffies + (seconds * HZ))) { - list_del(pos); - kfree(network_map); - } - } -} - -int slsi_roam_channel_cache_get_channels_int(struct net_device *dev, struct slsi_roaming_network_map_entry *network_map, u8 *channels) -{ - int index = 0; - int i; - - SLSI_UNUSED_PARAMETER(dev); - - /* 2.4 Ghz Channels */ - for (i = 1; i <= 14; i++) - if (network_map->channels_24_ghz & (1 << i)) { - channels[index] = i; - index++; - } - - /* 5 Ghz Uni1 Channels */ - for (i = 36; i <= 64; i += 4) - if (network_map->channels_5_ghz & (1 << ((i - 36) / 4))) { - channels[index] = i; - index++; - } - - /* 5 Ghz Uni2 Channels */ - for (i = 100; i <= 140; i += 4) - if (network_map->channels_5_ghz & (1 << (8 + ((i - 100) / 4)))) { - channels[index] = i; - index++; - } - - /* 5 Ghz Uni3 Channels */ - for (i = 149; i <= 165; i += 4) - if (network_map->channels_5_ghz & (1 << (24 + ((i - 149) / 4)))) { - channels[index] = i; - index++; - } - return index; -} - -static struct slsi_roaming_network_map_entry *slsi_roam_channel_cache_get(struct net_device *dev, const u8 *ssid) -{ - struct slsi_roaming_network_map_entry *network_map = NULL; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct list_head *pos; - - if (WARN_ON(!ssid)) - return NULL; - - list_for_each(pos, &ndev_vif->sta.network_map) { - network_map = list_entry(pos, struct slsi_roaming_network_map_entry, list); - if (network_map->ssid.ssid_len == ssid[1] && - memcmp(network_map->ssid.ssid, &ssid[2], ssid[1]) == 0) - break; - } - return network_map; -} - -u32 slsi_roam_channel_cache_get_channels(struct net_device *dev, const u8 *ssid, u8 *channels) -{ - u32 channels_count = 0; - struct slsi_roaming_network_map_entry *network_map; - - network_map = slsi_roam_channel_cache_get(dev, ssid); - if (network_map) - channels_count = slsi_roam_channel_cache_get_channels_int(dev, network_map, channels); - - return channels_count; -} - -static bool slsi_roam_channel_cache_single_ap(struct net_device *dev, const u8 *ssid) -{ - bool only_one_ap_seen = true; - struct slsi_roaming_network_map_entry *network_map; - - network_map = slsi_roam_channel_cache_get(dev, ssid); - if (network_map) - only_one_ap_seen = network_map->only_one_ap_seen; - - return only_one_ap_seen; -} - -int slsi_roaming_scan_configure_channels(struct slsi_dev *sdev, struct net_device *dev, const u8 *ssid, u8 *channels) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u32 cached_channels_count; - - SLSI_UNUSED_PARAMETER(sdev); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - WARN_ON(!ndev_vif->activated); - WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION); - - cached_channels_count = slsi_roam_channel_cache_get_channels(dev, ssid, channels); - if (slsi_roam_channel_cache_single_ap(dev, ssid)) { - SLSI_NET_DBG3(dev, SLSI_MLME, "Skip Roaming Scan for Single AP %.*s\n", ssid[1], &ssid[2]); - return 0; - } - - SLSI_NET_DBG3(dev, SLSI_MLME, "Roaming Scan Channels. %d cached\n", cached_channels_count); - - return cached_channels_count; -} - -int slsi_send_acs_event(struct slsi_dev *sdev, struct slsi_acs_selected_channels acs_selected_channels) -{ - struct sk_buff *skb = NULL; - u8 err = 0; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, - SLSI_NL80211_VENDOR_ACS_EVENT, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, - SLSI_NL80211_VENDOR_ACS_EVENT, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for VENDOR ACS event\n"); - return -ENOMEM; - } - err |= nla_put_u8(skb, SLSI_ACS_ATTR_PRIMARY_CHANNEL, acs_selected_channels.pri_channel); - err |= nla_put_u8(skb, SLSI_ACS_ATTR_SECONDARY_CHANNEL, acs_selected_channels.sec_channel); - err |= nla_put_u8(skb, SLSI_ACS_ATTR_VHT_SEG0_CENTER_CHANNEL, acs_selected_channels.vht_seg0_center_ch); - err |= nla_put_u8(skb, SLSI_ACS_ATTR_VHT_SEG1_CENTER_CHANNEL, acs_selected_channels.vht_seg1_center_ch); - err |= nla_put_u16(skb, SLSI_ACS_ATTR_CHWIDTH, acs_selected_channels.ch_width); - err |= nla_put_u8(skb, SLSI_ACS_ATTR_HW_MODE, acs_selected_channels.hw_mode); - SLSI_DBG3(sdev, SLSI_MLME, "pri_channel=%d,sec_channel=%d,vht_seg0_center_ch=%d," - "vht_seg1_center_ch=%d, ch_width=%d, hw_mode=%d\n", - acs_selected_channels.pri_channel, acs_selected_channels.sec_channel, - acs_selected_channels.vht_seg0_center_ch, acs_selected_channels.vht_seg1_center_ch, - acs_selected_channels.ch_width, acs_selected_channels.hw_mode); - if (err) { - SLSI_ERR_NODEV("Failed nla_put err=%d\n", err); - slsi_kfree_skb(skb); - return -EINVAL; - } - SLSI_INFO(sdev, "Event: SLSI_NL80211_VENDOR_ACS_EVENT(%d)\n", SLSI_NL80211_VENDOR_ACS_EVENT); - cfg80211_vendor_event(skb, GFP_KERNEL); - return 0; -} - -#ifdef CONFIG_SCSC_WLAN_WES_NCHO -int slsi_is_wes_action_frame(const struct ieee80211_mgmt *mgmt) -{ - int r = 0; - /* Vendor specific Action (0x7f), SAMSUNG OUI (0x00, 0x00, 0xf0) */ - u8 wes_vs_action_frame[4] = { 0x7f, 0x00, 0x00, 0xf0 }; - u8 *action = (u8 *)&mgmt->u.action; - - if (memcmp(action, wes_vs_action_frame, 4) == 0) - r = 1; - - return r; -} -#endif - -static u32 slsi_remap_reg_rule_flags(u8 flags) -{ - u32 remapped_flags = 0; - - if (flags & SLSI_REGULATORY_DFS) - remapped_flags |= NL80211_RRF_DFS; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (flags & SLSI_REGULATORY_NO_OFDM) - remapped_flags |= NL80211_RRF_NO_OFDM; -#endif -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 13, 0)) - if (flags & SLSI_REGULATORY_NO_IR) - remapped_flags |= NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS; -#endif - if (flags & SLSI_REGULATORY_NO_INDOOR) - remapped_flags |= NL80211_RRF_NO_INDOOR; - if (flags & SLSI_REGULATORY_NO_OUTDOOR) - remapped_flags |= NL80211_RRF_NO_OUTDOOR; - - return remapped_flags; -} - -static void slsi_reg_mib_to_regd(struct slsi_mib_data *mib, struct slsi_802_11d_reg_domain *domain_info) -{ - int i = 0; - int num_rules = 0; - u16 freq; - u8 byte_val; - struct ieee80211_reg_rule *reg_rule; - - domain_info->regdomain->alpha2[0] = *(u8 *)(&mib->data[i]); - i++; - - domain_info->regdomain->alpha2[1] = *(u8 *)(&mib->data[i]); - i++; - - domain_info->regdomain->dfs_region = *(u8 *)(&mib->data[i]); - i++; - - while (i < mib->dataLength) { - reg_rule = &domain_info->regdomain->reg_rules[num_rules]; - - /* start freq 2 bytes */ - freq = __le16_to_cpu(*(u16 *)(&mib->data[i])); - reg_rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq); - - /* end freq 2 bytes */ - freq = __le16_to_cpu(*(u16 *)(&mib->data[i + 2])); - reg_rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq); - - /* Max Bandwidth 1 byte */ - byte_val = *(u8 *)(&mib->data[i + 4]); - reg_rule->freq_range.max_bandwidth_khz = MHZ_TO_KHZ(byte_val); - - /* max_antenna_gain is obsolute now.*/ - reg_rule->power_rule.max_antenna_gain = 0; - - /* Max Power 1 byte */ - byte_val = *(u8 *)(&mib->data[i + 5]); - reg_rule->power_rule.max_eirp = DBM_TO_MBM(byte_val); - - /* Flags 1 byte */ - reg_rule->flags = slsi_remap_reg_rule_flags(*(u8 *)(&mib->data[i + 6])); - - i += 7; - - num_rules++; /* Num of reg rules */ - } - - domain_info->regdomain->n_reg_rules = num_rules; -} - -void slsi_reset_channel_flags(struct slsi_dev *sdev) -{ - enum nl80211_band band; - struct ieee80211_channel *chan; - int i; - struct wiphy *wiphy = sdev->wiphy; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - for (band = 0; band < NUM_NL80211_BANDS; band++) { -#else - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { -#endif - if (!wiphy->bands[band]) - continue; - for (i = 0; i < wiphy->bands[band]->n_channels; i++) { - chan = &wiphy->bands[band]->channels[i]; - chan->flags = 0; - } - } -} - -int slsi_read_regulatory_rules(struct slsi_dev *sdev, struct slsi_802_11d_reg_domain *domain_info, const char *alpha2) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_entry mib_val; - int r = 0; - int rx_len = 0; - int len = 0; - int index; - - index = slsi_country_to_index(domain_info, alpha2); - - if (index == -1) { - SLSI_ERR(sdev, "Unsupported index\n"); - return -EINVAL; - } - - slsi_mib_encode_get(&mibreq, SLSI_PSID_UNIFI_REGULATORY_PARAMETERS, index); - - /* Max of 6 regulatory constraints. - * each constraint start_freq(2 byte), end_freq(2 byte), Band width(1 byte), Max power(1 byte), - * rules flag (1 byte) - * firmware can have a max of 6 rules for a country. - */ - /* PSID header (5 bytes) + ((3 bytes) alpha2 code + dfs) + (max of 50 regulatory rules * 7 bytes each row) + MIB status(1) */ - mibrsp.dataLength = 5 + 3 + (SLSI_MIB_REG_RULES_MAX * 7) + 1; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_ERR(sdev, "Failed to alloc for Mib response\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, - mibrsp.data, mibrsp.dataLength, &rx_len); - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = rx_len; - - len = slsi_mib_decode(&mibrsp, &mib_val); - - if (len == 0) { - kfree(mibrsp.data); - SLSI_ERR(sdev, "Mib decode error\n"); - return -EINVAL; - } - slsi_reg_mib_to_regd(&mib_val.value.u.octetValue, domain_info); - } else { - SLSI_ERR(sdev, "Mib read failed (error: %d)\n", r); - } - - kfree(mibrsp.data); - return r; -} - -static int slsi_country_to_index(struct slsi_802_11d_reg_domain *domain_info, const char *alpha2) -{ - int index = 0; - bool index_found = false; - - SLSI_DBG3_NODEV(SLSI_MLME, "\n"); - if (domain_info->countrylist) { - for (index = 0; index < domain_info->country_len; index += 2) { - if (memcmp(&domain_info->countrylist[index], alpha2, 2) == 0) { - index_found = true; - break; - } - } - - /* If the set country is not present in the country list, fall back to - * world domain i.e. regulatory rules index = 1 - */ - if (index_found) - return (index / 2) + 1; - else - return 1; - } - - return -1; -} - -/* Set the rssi boost value of a particular band as set in the SETJOINPREFER command*/ -int slsi_set_mib_rssi_boost(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int index, int boost) -{ - struct slsi_mib_data mib_data = { 0, NULL }; - int error = SLSI_MIB_STATUS_FAILURE; - - SLSI_DBG2(sdev, SLSI_MLME, "Set rssi boost: %d\n", boost); - WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->device_config_mutex)); - if (slsi_mib_encode_int(&mib_data, psid, boost, index) == SLSI_MIB_STATUS_SUCCESS) - if (mib_data.dataLength) { - error = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - if (error) - SLSI_ERR(sdev, "Err Setting MIB failed. error = %d\n", error); - kfree(mib_data.data); - } - - return error; -} - -#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE -int slsi_set_mib_soft_roaming_enabled(struct slsi_dev *sdev, struct net_device *dev, bool enable) -{ - struct slsi_mib_data mib_data = { 0, NULL }; - int error = SLSI_MIB_STATUS_FAILURE; - - if (slsi_mib_encode_bool(&mib_data, SLSI_PSID_UNIFI_ROAM_SOFT_ROAMING_ENABLED, - enable, 0) == SLSI_MIB_STATUS_SUCCESS) - if (mib_data.dataLength) { - error = slsi_mlme_set(sdev, dev, mib_data.data, mib_data.dataLength); - if (error) - SLSI_ERR(sdev, "Err Setting MIB failed. error = %d\n", error); - kfree(mib_data.data); - } - - return error; -} -#endif - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -int slsi_read_enhanced_arp_rx_count_by_lower_mac(struct slsi_dev *sdev, struct net_device *dev, u16 psid) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_entry mib_val; - int r = 0; - int rx_len = 0; - int len = 0; - - SLSI_DBG3(sdev, SLSI_MLME, "\n"); - - slsi_mib_encode_get(&mibreq, psid, 0); - - mibrsp.dataLength = 10; /* PSID header(5) + uint 4 bytes + status(1) */ - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_ERR(sdev, "Failed to alloc for Mib response\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, dev, mibreq.data, mibreq.dataLength, mibrsp.data, - mibrsp.dataLength, &rx_len); - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = rx_len; - len = slsi_mib_decode(&mibrsp, &mib_val); - - if (len == 0) { - kfree(mibrsp.data); - SLSI_ERR(sdev, "Mib decode error\n"); - return -EINVAL; - } - ndev_vif->enhanced_arp_stats.arp_rsp_rx_count_by_lower_mac = mib_val.value.u.uintValue; - } else { - SLSI_ERR(sdev, "Mib read failed (error: %d)\n", r); - } - - kfree(mibrsp.data); - return r; -} - -void slsi_fill_enhanced_arp_out_of_order_drop_counter(struct netdev_vif *ndev_vif, - struct sk_buff *skb) -{ - struct ethhdr *eth_hdr; - u8 *frame; - u16 arp_opcode; - -#ifdef CONFIG_SCSC_SMAPPER - /* Check if the payload is in the SMAPPER entry */ - if (fapi_get_u16(skb, u.ma_unitdata_ind.bulk_data_descriptor) == FAPI_BULKDATADESCRIPTOR_SMAPPER) { - frame = slsi_hip_get_skb_data_from_smapper(ndev_vif->sdev, skb); - eth_hdr = (struct ethhdr *)frame; - if (!(eth_hdr)) { - SLSI_DBG2(ndev_vif->sdev, SLSI_RX, "SKB from SMAPPER is NULL\n"); - return; - } - frame = frame + sizeof(struct ethhdr); - } else { - frame = fapi_get_data(skb) + sizeof(struct ethhdr); - eth_hdr = (struct ethhdr *)fapi_get_data(skb); - } -#else - frame = fapi_get_data(skb) + sizeof(struct ethhdr); - eth_hdr = (struct ethhdr *)fapi_get_data(skb); -#endif - - arp_opcode = frame[SLSI_ARP_OPCODE_OFFSET] << 8 | frame[SLSI_ARP_OPCODE_OFFSET + 1]; - /* check if sender ip = gateway ip and it is an ARP response*/ - if ((ntohs(eth_hdr->h_proto) == ETH_P_ARP) && - (arp_opcode == SLSI_ARP_REPLY_OPCODE) && - !SLSI_IS_GRATUITOUS_ARP(frame) && - !memcmp(&frame[SLSI_ARP_SRC_IP_ADDR_OFFSET], &ndev_vif->target_ip_addr, 4)) - ndev_vif->enhanced_arp_stats.arp_rsp_count_out_of_order_drop++; -} -#endif - -void slsi_modify_ies_on_channel_switch(struct net_device *dev, struct cfg80211_ap_settings *settings, - u8 *ds_params_ie, u8 *ht_operation_ie, struct ieee80211_mgmt *mgmt, - u16 beacon_ie_head_len) -{ - slsi_modify_ies(dev, WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, - beacon_ie_head_len, 2, ieee80211_frequency_to_channel(settings->chandef.chan->center_freq)); - - slsi_modify_ies(dev, WLAN_EID_HT_OPERATION, (u8 *)settings->beacon.tail, - settings->beacon.tail_len, 2, - ieee80211_frequency_to_channel(settings->chandef.chan->center_freq)); -} - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -void slsi_extract_valid_wifi_sharing_channels(struct slsi_dev *sdev) -{ - int i, j; - int p = 0; - int k = (SLSI_MAX_CHAN_5G_BAND - 1); - int flag = 0; - - for (i = 4; i >= 0 ; i--) { - for (j = 0; j <= 7 ; j++) { - if ((i == 4) && (j == 0)) - j = 1; - if (sdev->wifi_sharing_5ghz_channel[i] & (u8)(1 << (7 - j))) - sdev->valid_5g_freq[p] = slsi_5ghz_all_channels[k]; - else - sdev->valid_5g_freq[p] = 0; - p++; - k--; - if (p == SLSI_MAX_CHAN_5G_BAND) { - flag = 1; - break; - } - } - if (flag == 1) - break; - } -} - -bool slsi_if_valid_wifi_sharing_channel(struct slsi_dev *sdev, int freq) -{ - int i; - - for (i = 0; i <= (SLSI_MAX_CHAN_5G_BAND - 1) ; i++) { - if (sdev->valid_5g_freq[i] == freq) - return 1; - } - return 0; -} - -int slsi_check_if_non_indoor_non_dfs_channel(struct slsi_dev *sdev, int freq) -{ - struct ieee80211_channel *channel = NULL; - u32 chan_flags = 0; - - channel = ieee80211_get_channel(sdev->wiphy, freq); - if (!channel) { - SLSI_ERR(sdev, "Invalid frequency %d used to start AP. Channel not found\n", freq); - return 0; - } - - chan_flags = (IEEE80211_CHAN_INDOOR_ONLY | IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_DISABLED | -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13) - IEEE80211_CHAN_PASSIVE_SCAN -#else - IEEE80211_CHAN_NO_IR -#endif - ); - - if ((channel->flags) & chan_flags) - return 0; - - return 1; -} - -int slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *settings, - struct slsi_dev *sdev, int *wifi_sharing_channel_switched) -{ - struct net_device *sta_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - struct netdev_vif *ndev_sta_vif = netdev_priv(sta_dev); - int sta_frequency = ndev_sta_vif->chan->center_freq; - - SLSI_DBG1(sdev, SLSI_CFG80211, "Station connected on frequency: %d\n", sta_frequency); - - if (((sta_frequency) / 1000) == 2) { /*For 2.4GHz */ - /*if single antenna*/ -#ifdef CONFIG_SCSC_WLAN_SINGLE_ANTENNA - if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *wifi_sharing_channel_switched = 1; - settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); - settings->chandef.center_freq1 = sta_frequency; - } -#else - /* if dual antenna */ - if ((((settings->chandef.chan->center_freq) / 1000) == 5) && - !(slsi_check_if_channel_restricted_already(sdev, - ieee80211_frequency_to_channel(settings->chandef.chan->center_freq))) && - slsi_if_valid_wifi_sharing_channel(sdev, settings->chandef.chan->center_freq) && - slsi_check_if_non_indoor_non_dfs_channel(sdev, settings->chandef.chan->center_freq)) { - settings->chandef.chan = ieee80211_get_channel(wiphy, settings->chandef.chan->center_freq); - settings->chandef.center_freq1 = settings->chandef.chan->center_freq; - } else { - if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *wifi_sharing_channel_switched = 1; - settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); - settings->chandef.center_freq1 = sta_frequency; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (!sdev->fw_SoftAp_2g_40mhz_enabled && (settings->chandef.width == NL80211_CHAN_WIDTH_40)) - settings->chandef.width = NL80211_CHAN_WIDTH_20; -#endif - } - } -#endif - } - - else { /* For 5GHz */ - /* For single antenna */ -#ifdef CONFIG_SCSC_WLAN_SINGLE_ANTENNA - if (!slsi_check_if_non_indoor_non_dfs_channel(sdev, sta_frequency)) - return 1; /*AP cannot start on indoor channel so we will reject request from the host*/ - if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *wifi_sharing_channel_switched = 1; - settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); - settings->chandef.center_freq1 = sta_frequency; - } - /* Single antenna end */ -#else - /* For Dual Antenna */ - if (((settings->chandef.chan->center_freq) / 1000) == 5) { - if (!(slsi_check_if_channel_restricted_already(sdev, - ieee80211_frequency_to_channel(sta_frequency))) && - slsi_if_valid_wifi_sharing_channel(sdev, sta_frequency) && - slsi_check_if_non_indoor_non_dfs_channel(sdev, sta_frequency)) { - if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *wifi_sharing_channel_switched = 1; - settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); - } - } else { - *wifi_sharing_channel_switched = 1; - settings->chandef.chan = ieee80211_get_channel(wiphy, SLSI_2G_CHANNEL_ONE); - settings->chandef.center_freq1 = SLSI_2G_CHANNEL_ONE; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (!sdev->fw_SoftAp_2g_40mhz_enabled && (settings->chandef.width == NL80211_CHAN_WIDTH_40)) - settings->chandef.width = NL80211_CHAN_WIDTH_20; -#endif - } - } -#endif - } - - SLSI_DBG1(sdev, SLSI_CFG80211, "AP frequency chosen: %d\n", settings->chandef.chan->center_freq); - return 0; -} - -int slsi_get_byte_position(int bit) -{ - int byte_pos = 0; - - /* bit will find which bit, pos will tell which pos in the array */ - if (bit >= 8 && bit <= 15) - byte_pos = 1; - else if (bit >= 16 && bit <= 23) - byte_pos = 2; - else if (bit >= 24 && bit <= 31) - byte_pos = 3; - else if (bit >= 32 && bit <= 38) - byte_pos = 4; - - return byte_pos; -} - -int slsi_check_if_channel_restricted_already(struct slsi_dev *sdev, int channel) -{ - int i; - - for (i = 0; i < sdev->num_5g_restricted_channels; i++) - if (sdev->wifi_sharing_5g_restricted_channels[i] == channel) - return 1; - - return 0; -} - -int slsi_set_mib_wifi_sharing_5ghz_channel(struct slsi_dev *sdev, u16 psid, int res, - int offset, int readbyte, char *arg) -{ - struct slsi_mib_entry mib_entry; - struct slsi_mib_data buffer = { 0, NULL }; - int error = SLSI_MIB_STATUS_FAILURE; - int i; - int bit = 0; /* find which bit to set */ - int byte_pos = 0; /* which index to set bit among 8 larger set*/ - int freq; - int j; - int bit_mask; - int num_channels; - int p = 0; - int new_channels = 0; - int freq_to_be_checked = 0; - - mib_entry.value.type = SLSI_MIB_TYPE_OCTET; - mib_entry.value.u.octetValue.dataLength = 8; - mib_entry.value.u.octetValue.data = kmalloc(64, GFP_KERNEL); - - if (!mib_entry.value.u.octetValue.data) { - error = -ENOMEM; - goto exit; - } - - for (i = 0; i < 8; i++) - mib_entry.value.u.octetValue.data[i] = sdev->wifi_sharing_5ghz_channel[i]; - - if (res == 0) { - for (i = 0; i < 25 ; i++) - sdev->wifi_sharing_5g_restricted_channels[i] = 0; - sdev->num_5g_restricted_channels = 0; - new_channels = 1; - } else if (res == -1) { - for (i = 0; i < 8; i++) - mib_entry.value.u.octetValue.data[i] = 0x00; - - for (i = 0; i < 25 ; i++) - sdev->wifi_sharing_5g_restricted_channels[i] = 0; - - for (i = 24; i >= 0 ; i--) { - if (sdev->valid_5g_freq[i] != 0) - sdev->wifi_sharing_5g_restricted_channels[p++] = - ieee80211_frequency_to_channel(sdev->valid_5g_freq[i]); - } - sdev->num_5g_restricted_channels = p; - new_channels = 1; - } else { - num_channels = res; - - for (i = 0; i < num_channels; i++) { - offset = offset + readbyte + 1; - readbyte = slsi_str_to_int(&arg[offset], &res); - /*if channel is not already present , then only add it*/ - freq_to_be_checked = ieee80211_channel_to_frequency(res, NL80211_BAND_5GHZ); - if (slsi_if_valid_wifi_sharing_channel(sdev, freq_to_be_checked) && - (!slsi_check_if_channel_restricted_already(sdev, res))) { - if ((sdev->num_5g_restricted_channels) > 24) - break; - new_channels = 1; - sdev->wifi_sharing_5g_restricted_channels[(sdev->num_5g_restricted_channels)++] = res; - } - } - - if (new_channels) { - for (i = 0; i < (sdev->num_5g_restricted_channels); i++) { - freq = ieee80211_channel_to_frequency(sdev->wifi_sharing_5g_restricted_channels[i], - NL80211_BAND_5GHZ); - for (j = 0; j < 25; j++) { - if (slsi_5ghz_all_channels[j] == freq) { - bit = j + 14; - break; - } - } - byte_pos = slsi_get_byte_position(bit); - bit_mask = (bit % 8); - mib_entry.value.u.octetValue.data[byte_pos] &= (u8)(~(1 << (bit_mask))); - } - } - } - - if (new_channels) { - error = slsi_mib_encode_octet(&buffer, psid, mib_entry.value.u.octetValue.dataLength, - mib_entry.value.u.octetValue.data, 0); - if (error != SLSI_MIB_STATUS_SUCCESS) { - error = -ENOMEM; - goto exit; - } - - if (WARN_ON(buffer.dataLength == 0)) { - error = -EINVAL; - goto exit; - } - - error = slsi_mlme_set(sdev, NULL, buffer.data, buffer.dataLength); - kfree(buffer.data); - - if (!error) - return 0; - -exit: - SLSI_ERR(sdev, "Error in setting wifi sharing 5ghz channel. error = %d\n", error); - return error; - } - - return 0; -} -#endif -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION -int slsi_set_mac_randomisation_mask(struct slsi_dev *sdev, u8 *mac_address_mask) -{ - int r = 0; - struct slsi_mib_data mib_data = { 0, NULL }; - - SLSI_DBG1(sdev, SLSI_CFG80211, "Mask is :%pM\n", mac_address_mask); - r = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_MAC_ADDRESS_RANDOMISATION_MASK, ETH_ALEN, - mac_address_mask, 0); - if (r != SLSI_MIB_STATUS_SUCCESS) { - return -ENOMEM; - } - - r = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - kfree(mib_data.data); - - if (r != SLSI_MIB_STATUS_SUCCESS) { - SLSI_ERR(sdev, "Err setting unifiMacAddrRandomistaionMask MIB. error = %d\n", r); - if (sdev->scan_addr_set) { - struct slsi_mib_data mib_data_randomization_activated = { 0, NULL }; - - r = slsi_mib_encode_bool(&mib_data_randomization_activated, - SLSI_PSID_UNIFI_MAC_ADDRESS_RANDOMISATION, 1, 0); - if (r != SLSI_MIB_STATUS_SUCCESS) - return -ENOMEM; - - r = slsi_mlme_set(sdev, NULL, mib_data_randomization_activated.data, - mib_data_randomization_activated.dataLength); - - kfree(mib_data_randomization_activated.data); - - if (r) { - SLSI_ERR(sdev, "Err setting unifiMacAddrRandomistaionActivated MIB. error = %d\n", r); - return r; - } - } - } - return r; -} -#endif -/* Set the new country code and read the regulatory parameters of updated country. */ -int slsi_set_country_update_regd(struct slsi_dev *sdev, const char *alpha2_code, int size) -{ - struct slsi_mib_data mib_data = { 0, NULL }; - char alpha2[4]; - int error = 0; - - SLSI_DBG2(sdev, SLSI_MLME, "Set country code: %c%c\n", alpha2_code[0], alpha2_code[1]); - - if (size == 4) { - memcpy(alpha2, alpha2_code, 4); - } else { - memcpy(alpha2, alpha2_code, 3); - alpha2[3] = '\0'; - } - - if (memcmp(alpha2, sdev->device_config.domain_info.regdomain->alpha2, 2) == 0) { - SLSI_DBG3(sdev, SLSI_MLME, "Country is already set to the requested country code\n"); - return 0; - } - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - - error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_DEFAULT_COUNTRY, 3, alpha2, 0); - if (error != SLSI_MIB_STATUS_SUCCESS) { - error = -ENOMEM; - goto exit; - } - - if (WARN_ON(mib_data.dataLength == 0)) { - error = -EINVAL; - goto exit; - } - - error = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - - kfree(mib_data.data); - - if (error) { - SLSI_ERR(sdev, "Err setting country error = %d\n", error); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return -1; - } - - /* Read the regulatory params for the country */ - if (slsi_read_regulatory_rules(sdev, &sdev->device_config.domain_info, alpha2) == 0) { - slsi_reset_channel_flags(sdev); - wiphy_apply_custom_regulatory(sdev->wiphy, sdev->device_config.domain_info.regdomain); - slsi_update_supported_channels_regd_flags(sdev); - } - -exit: - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return error; -} - -/* Read unifiDisconnectTimeOut MIB */ -int slsi_read_disconnect_ind_timeout(struct slsi_dev *sdev, u16 psid) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_entry mib_val; - int r = 0; - int rx_len = 0; - int len = 0; - - SLSI_DBG3(sdev, SLSI_MLME, "\n"); - - slsi_mib_encode_get(&mibreq, psid, 0); - - mibrsp.dataLength = 10; /* PSID header(5) + uint 4 bytes + status(1) */ - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_ERR(sdev, "Failed to alloc for Mib response\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, mibrsp.data, - mibrsp.dataLength, &rx_len); - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = rx_len; - len = slsi_mib_decode(&mibrsp, &mib_val); - - if (len == 0) { - kfree(mibrsp.data); - SLSI_ERR(sdev, "Mib decode error\n"); - return -EINVAL; - } - /* Add additional 1 sec delay */ - sdev->device_config.ap_disconnect_ind_timeout = ((mib_val.value.u.uintValue + 1) * 1000); - } else { - SLSI_ERR(sdev, "Mib read failed (error: %d)\n", r); - } - - kfree(mibrsp.data); - return r; -} - -/* Read unifiDefaultCountry MIB */ -int slsi_read_default_country(struct slsi_dev *sdev, u8 *alpha2, u16 index) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_entry mib_val; - int r = 0; - int rx_len = 0; - int len = 0; - - slsi_mib_encode_get(&mibreq, SLSI_PSID_UNIFI_DEFAULT_COUNTRY, index); - - mibrsp.dataLength = 11; /* PSID header(5) + index(1) + country code alpha2 3 bytes + status(1) */ - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_ERR(sdev, "Failed to alloc for Mib response\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, mibrsp.data, - mibrsp.dataLength, &rx_len); - - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = rx_len; - len = slsi_mib_decode(&mibrsp, &mib_val); - - if (len == 0) { - kfree(mibrsp.data); - SLSI_ERR(sdev, "Mib decode error\n"); - return -EINVAL; - } - memcpy(alpha2, mib_val.value.u.octetValue.data, 2); - } else { - SLSI_ERR(sdev, "Mib read failed (error: %d)\n", r); - } - - kfree(mibrsp.data); - return r; -} - -int slsi_copy_country_table(struct slsi_dev *sdev, struct slsi_mib_data *mib, int len) -{ - SLSI_DBG3(sdev, SLSI_MLME, "\n"); - - kfree(sdev->device_config.domain_info.countrylist); - sdev->device_config.domain_info.countrylist = kmalloc(len, GFP_KERNEL); - - if (!sdev->device_config.domain_info.countrylist) { - SLSI_ERR(sdev, "kmalloc failed\n"); - return -EINVAL; - } - - if (!mib || !mib->data) { - SLSI_ERR(sdev, "Invalid MIB country table\n"); - return -EINVAL; - } - - memcpy(sdev->device_config.domain_info.countrylist, mib->data, len); - sdev->device_config.domain_info.country_len = len; - - return 0; -} - -/* Read unifi country list */ -int slsi_read_unifi_countrylist(struct slsi_dev *sdev, u16 psid) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_entry mib_val; - int r = 0; - int rx_len = 0; - int len = 0; - int ret; - - slsi_mib_encode_get(&mibreq, psid, 0); - - /* Fixed fields len (5) : 2 bytes(PSID) + 2 bytes (Len) + 1 byte (status) - * Data : 148 countries??? for SLSI_PSID_UNIFI_COUNTRY_LIST - */ - mibrsp.dataLength = 5 + (NUM_COUNTRY * 2); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_ERR(sdev, "Failed to alloc for Mib response\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, mibrsp.data, - mibrsp.dataLength, &rx_len); - - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = rx_len; - len = slsi_mib_decode(&mibrsp, &mib_val); - - if (len == 0) { - kfree(mibrsp.data); - return -EINVAL; - } - ret = slsi_copy_country_table(sdev, &mib_val.value.u.octetValue, len); - if (ret < 0) { - kfree(mibrsp.data); - return ret; - } - } else { - SLSI_ERR(sdev, "Mib read failed (error: %d)\n", r); - } - - kfree(mibrsp.data); - return r; -} - -void slsi_regd_deinit(struct slsi_dev *sdev) -{ - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "slsi_regd_deinit\n"); - - kfree(sdev->device_config.domain_info.countrylist); -} - -void slsi_clear_offchannel_data(struct slsi_dev *sdev, bool acquire_lock) -{ - struct net_device *dev = NULL; - struct netdev_vif *ndev_vif = NULL; - - dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN); - if (WARN_ON(!dev)) { - SLSI_ERR(sdev, "No Group net dev found\n"); - return; - } - ndev_vif = netdev_priv(dev); - - if (acquire_lock) - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - /* Reset dwell time should be sent on group vif */ - (void)slsi_mlme_reset_dwell_time(sdev, dev); - - if (acquire_lock) - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - sdev->p2p_group_exp_frame = SLSI_P2P_PA_INVALID; -} - -static void slsi_hs2_unsync_vif_delete_work(struct work_struct *work) -{ - struct netdev_vif *ndev_vif = container_of((struct delayed_work *)work, struct netdev_vif, unsync.hs2_del_vif_work); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_CFG80211, "Delete HS vif duration expired - Deactivate unsync vif\n"); - slsi_wlan_unsync_vif_deactivate(ndev_vif->sdev, ndev_vif->wdev.netdev, true); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -int slsi_wlan_unsync_vif_activate(struct slsi_dev *sdev, struct net_device *dev, - struct ieee80211_channel *chan, u16 wait) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - u8 device_address[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - u32 action_frame_bmap; - - SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "Activate wlan unsync vif\n"); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - ndev_vif->vif_type = FAPI_VIFTYPE_UNSYNCHRONISED; - - /* Avoid suspend when wlan unsync VIF is active */ - slsi_wakelock(&sdev->wlan_wl); - - /* Interface address and device address are same for unsync vif */ - if (slsi_mlme_add_vif(sdev, dev, dev->dev_addr, device_address) != 0) { - SLSI_NET_ERR(dev, "add vif failed for wlan unsync vif\n"); - goto exit_with_error; - } - - if (slsi_vif_activated(sdev, dev) != 0) { - SLSI_NET_ERR(dev, "vif activate failed for wlan unsync vif\n"); - slsi_mlme_del_vif(sdev, dev); - goto exit_with_error; - } - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_VIF_ACTIVE; - INIT_DELAYED_WORK(&ndev_vif->unsync.hs2_del_vif_work, slsi_hs2_unsync_vif_delete_work); - action_frame_bmap = SLSI_ACTION_FRAME_PUBLIC | SLSI_ACTION_FRAME_RADIO_MEASUREMENT; - - r = slsi_mlme_register_action_frame(sdev, dev, action_frame_bmap, action_frame_bmap); - if (r != 0) { - SLSI_NET_ERR(dev, "slsi_mlme_register_action_frame failed: resultcode = %d, action_frame_bmap:%d\n", - r, action_frame_bmap); - goto exit_with_vif; - } - - if (slsi_mlme_set_channel(sdev, dev, chan, SLSI_FW_CHANNEL_DURATION_UNSPECIFIED, 0, 0) != 0) { - SLSI_NET_ERR(dev, "Set channel failed for wlan unsync vif\n"); - goto exit_with_vif; - } - ndev_vif->chan = chan; - ndev_vif->driver_channel = chan->hw_value; - return r; - -exit_with_vif: - slsi_wlan_unsync_vif_deactivate(sdev, dev, true); -exit_with_error: - slsi_wakeunlock(&sdev->wlan_wl); - return -EINVAL; -} - -/* Delete unsync vif - DON'T update the vif type */ -void slsi_wlan_unsync_vif_deactivate(struct slsi_dev *sdev, struct net_device *dev, bool hw_available) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "De-activate wlan unsync vif\n"); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (sdev->wlan_unsync_vif_state == WLAN_UNSYNC_NO_VIF) { - SLSI_NET_DBG1(dev, SLSI_INIT_DEINIT, "wlan unsync vif already deactivated\n"); - return; - } - - cancel_delayed_work(&ndev_vif->unsync.hs2_del_vif_work); - - /* slsi_vif_deactivated is not used here after slsi_mlme_del_vif - * as it modifies vif type as well - */ - if (hw_available) - slsi_mlme_del_vif(sdev, dev); - - slsi_wakeunlock(&sdev->wlan_wl); - - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_NO_VIF; - ndev_vif->activated = false; - ndev_vif->chan = NULL; - - (void)slsi_set_mgmt_tx_data(ndev_vif, 0, 0, NULL, 0); -} - -void slsi_scan_ind_timeout_handle(struct work_struct *work) -{ - struct netdev_vif *ndev_vif = container_of((struct delayed_work *)work, struct netdev_vif, scan_timeout_work); - struct net_device *dev = slsi_get_netdev(ndev_vif->sdev, ndev_vif->ifnum); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) { - if (ndev_vif->scan[SLSI_SCAN_HW_ID].requeue_timeout_work) { - queue_delayed_work(ndev_vif->sdev->device_wq, &ndev_vif->scan_timeout_work, - msecs_to_jiffies(SLSI_FW_SCAN_DONE_TIMEOUT_MSEC)); - ndev_vif->scan[SLSI_SCAN_HW_ID].requeue_timeout_work = false; - } else { - SLSI_WARN(ndev_vif->sdev, "Mlme_scan_done_ind not received\n"); - (void)slsi_mlme_del_scan(ndev_vif->sdev, dev, ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID, true); - slsi_scan_complete(ndev_vif->sdev, dev, SLSI_SCAN_HW_ID, false); - } - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -void slsi_update_supported_channels_regd_flags(struct slsi_dev *sdev) -{ - int i = 0; - struct wiphy *wiphy = sdev->wiphy; - struct ieee80211_channel *chan; - - /* If all channels are supported by chip no need disable any channel - * So return - */ - if (sdev->enabled_channel_count == 39) - return; - if (wiphy->bands[0]) { - for (i = 0; i < ARRAY_SIZE(sdev->supported_2g_channels); i++) { - if (sdev->supported_2g_channels[i] == 0) { - chan = &wiphy->bands[0]->channels[i]; - chan->flags |= IEEE80211_CHAN_DISABLED; - } - } - } - if (sdev->band_5g_supported && wiphy->bands[1]) { - for (i = 0; i < ARRAY_SIZE(sdev->supported_5g_channels); i++) { - if (sdev->supported_5g_channels[i] == 0) { - chan = &wiphy->bands[1]->channels[i]; - chan->flags |= IEEE80211_CHAN_DISABLED; - } - } - } -} - -int slsi_find_chan_idx(u16 chan, u8 hw_mode) -{ - int idx = 0, i = 0; - u16 slsi_5ghz_channels_list[25] = {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, - 136, 140, 144, 149, 153, 157, 161, 165}; - - if (hw_mode == SLSI_ACS_MODE_IEEE80211B || hw_mode == SLSI_ACS_MODE_IEEE80211G) { - idx = chan - 1; - return idx; - } - for (i = 0; i < 25; i++) { - if (chan == slsi_5ghz_channels_list[i]) { - idx = i; - break; - } - } - return idx; -} - -#ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS -/* Note : netdev_vif lock should be taken care by caller. */ -int slsi_set_num_antennas(struct net_device *dev, const u16 num_of_antennas) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - struct sk_buff *req; - struct sk_buff *cfm; - int ret = 0; - const bool is_sta = (ndev_vif->iftype == NL80211_IFTYPE_STATION); - const bool is_softap = (ndev_vif->iftype == NL80211_IFTYPE_AP); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (num_of_antennas > 2 || num_of_antennas == 0) { - SLSI_NET_ERR(dev, "Invalid num_of_antennas %hu\n", num_of_antennas); - return -EINVAL; - } - if (!is_sta && !is_softap) { - SLSI_NET_ERR(dev, "Invalid interface type %s\n", dev->name); - return -EPERM; - } - if (is_sta && (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_NET_ERR(dev, "sta is not in connected state\n"); - return -EPERM; - } - SLSI_NET_INFO(dev, "mlme_set_num_antennas_req(vif:%u num_of_antennas:%u)\n", ndev_vif->ifnum, num_of_antennas); - /* TODO: Change signal name to MLME_SET_NUM_ANTENNAS_REQ and MLME_SET_NUM_ANTENNAS_CFM. */ - req = fapi_alloc(mlme_set_num_antennas_req, MLME_SET_NUM_ANTENNAS_REQ, ndev_vif->ifnum, 0); - fapi_set_u16(req, u.mlme_set_num_antennas_req.vif, ndev_vif->ifnum); - fapi_set_u16(req, u.mlme_set_num_antennas_req.number_of_antennas, num_of_antennas); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_NUM_ANTENNAS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_num_antennas_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_num_antennas_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_num_antennas_cfm.result_code)); - ret = -EINVAL; - } - slsi_kfree_skb(cfm); - return ret; -} -#endif - -int slsi_set_latency_mode(struct net_device *dev, int latency_mode, int cmd_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int ret = 0; - u8 host_state; - - SLSI_DBG1(sdev, SLSI_CFG80211, "latency_mode = %d\n", latency_mode); - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - host_state = sdev->device_config.host_state; - - /* latency_mode =0 (Normal), latency_mode =1 (Low) */ - if (latency_mode) - host_state = host_state | SLSI_HOSTSTATE_LOW_LATENCY_ACTIVE; - else - host_state = host_state & ~SLSI_HOSTSTATE_LOW_LATENCY_ACTIVE; - - ret = slsi_mlme_set_host_state(sdev, dev, host_state); - if (ret != 0) - SLSI_NET_ERR(dev, "Error in setting the Host State, ret=%d", ret); - else - sdev->device_config.host_state = host_state; - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - return ret; -} diff --git a/drivers/net/wireless/scsc/mgt.h b/drivers/net/wireless/scsc/mgt.h deleted file mode 100755 index b61a5c620896..000000000000 --- a/drivers/net/wireless/scsc/mgt.h +++ /dev/null @@ -1,574 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef __SLSI_MGT_H__ -#define __SLSI_MGT_H__ - -#include - -#include "dev.h" -#include "debug.h" - -/* For 3.4.11 kernel support */ -#ifndef WLAN_OUI_MICROSOFT -#define WLAN_OUI_MICROSOFT 0x0050f2 -#define WLAN_OUI_TYPE_MICROSOFT_WPA 1 -#define WLAN_OUI_TYPE_MICROSOFT_WMM 2 -#define WLAN_OUI_TYPE_MICROSOFT_WPS 4 -#endif - -#define SLSI_COUNTRY_CODE_LEN 3 - -#define SLSI_EAPOL_TYPE_RSN_KEY (2) -#define SLSI_EAPOL_TYPE_WPA_KEY (254) - -#define SLSI_IEEE8021X_TYPE_EAPOL_KEY 3 -#define SLSI_IEEE8021X_TYPE_EAP_PACKET 0 - -#define SLSI_EAPOL_KEY_INFO_KEY_TYPE_BIT_IN_LOWER_BYTE BIT(3) /* Group = 0, Pairwise = 1 */ -#define SLSI_EAPOL_KEY_INFO_ACK_BIT_IN_LOWER_BYTE BIT(7) -#define SLSI_EAPOL_KEY_INFO_MIC_BIT_IN_HIGHER_BYTE BIT(0) -#define SLSI_EAPOL_KEY_INFO_SECURE_BIT_IN_HIGHER_BYTE BIT(1) -/* pkt_data would start from 802.1X Authentication field (pkt_data[0] = Version). - * For M4 packet, it will be something as below... member(size, position) - * Version (1, 0) + Type (1, 1) + Length (2, 2:3) + Descriptor Type (1, 4) + Key Information (2, 5:6) + - * key_length(2, 7:8) + replay_counter(8, 9:16) + key_nonce(32, 17:48) + key_iv(16, 49:64) + - * key_rsc (8, 65:72) + key_id(16, 73:80) + key_mic (16, 81:96) + key_data_length(2, 97:98) + - * keydata(key_data_length, 99:99+key_data_length) - */ -#define SLSI_EAPOL_IEEE8021X_TYPE_POS (1) -#define SLSI_EAPOL_TYPE_POS (4) -#define SLSI_EAPOL_KEY_INFO_HIGHER_BYTE_POS (5) -#define SLSI_EAPOL_KEY_INFO_LOWER_BYTE_POS (6) -#define SLSI_EAPOL_KEY_DATA_LENGTH_HIGHER_BYTE_POS (97) -#define SLSI_EAPOL_KEY_DATA_LENGTH_LOWER_BYTE_POS (98) - -#define SLSI_EAP_CODE_POS (4) -#define SLSI_EAP_PACKET_REQUEST (1) -#define SLSI_EAP_PACKET_RESPONSE (2) -#define SLSI_EAP_PACKET_SUCCESS (3) -#define SLSI_EAP_PACKET_FAILURE (4) -#define SLSI_EAP_TYPE_POS (8) -#define SLSI_EAP_TYPE_EXPANDED (254) -#define SLSI_EAP_OPCODE_POS (16) -#define SLSI_EAP_OPCODE_WSC_MSG (4) -#define SLSI_EAP_OPCODE_WSC_START (1) -#define SLSI_EAP_MSGTYPE_POS (27) -#define SLSI_EAP_MSGTYPE_M8 (12) -#define SLSI_EAP_WPS_DWELL_TIME (100000) /*100 ms */ -#define SLSI_EAP_TYPE_IDENTITY (1) - -#define SLSI_80211_AC_VO 0 -#define SLSI_80211_AC_VI 1 -#define SLSI_80211_AC_BE 2 -#define SLSI_80211_AC_BK 3 - -/* IF Number (Index) based checks */ -#define SLSI_IS_VIF_INDEX_WLAN(ndev_vif) (ndev_vif->ifnum == SLSI_NET_INDEX_WLAN) -#define SLSI_IS_VIF_INDEX_P2P(ndev_vif) (ndev_vif->ifnum == SLSI_NET_INDEX_P2P) -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#define SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif) ((ndev_vif->ifnum == SLSI_NET_INDEX_P2PX_SWLAN) &&\ - (sdev->netdev_ap != sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN])) -#define SLSI_IS_VIF_INDEX_MHS(sdev, ndev_vif) ((ndev_vif->ifnum == SLSI_NET_INDEX_P2PX_SWLAN) &&\ - (sdev->netdev_ap == sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN])) -#else -#define SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif) (ndev_vif->ifnum == SLSI_NET_INDEX_P2PX_SWLAN) -#endif -#define SLSI_IS_VIF_INDEX_NAN(ndev_vif) ((ndev_vif)->ifnum == SLSI_NET_INDEX_NAN) - -/* Check for P2P unsync vif type */ -#define SLSI_IS_P2P_UNSYNC_VIF(ndev_vif) ((ndev_vif->ifnum == SLSI_NET_INDEX_P2P) && (ndev_vif->vif_type == FAPI_VIFTYPE_UNSYNCHRONISED)) - -/* Check for HS unsync vif type */ -#define SLSI_IS_HS2_UNSYNC_VIF(ndev_vif) ((ndev_vif->ifnum == SLSI_NET_INDEX_WLAN) && (ndev_vif->vif_type == FAPI_VIFTYPE_UNSYNCHRONISED)) - -/* Check for P2P Group role */ -#define SLSI_IS_P2P_GROUP_STATE(sdev) ((sdev->p2p_state == P2P_GROUP_FORMED_GO) || (sdev->p2p_state == P2P_GROUP_FORMED_CLI)) - -/* Extra delay to wait after MLME-Roam.Response before obtaining roam reports */ -#define SLSI_STA_ROAM_REPORT_EXTRA_DELAY_MSEC 50 - -/* Extra duration in addition to ROC duration - For any workqueue scheduling delay */ -#define SLSI_P2P_ROC_EXTRA_MSEC 10 - -/* Extra duration to retain unsync vif even after ROC/mgmt_tx completes */ -#define SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC 2000 -/* Extra duration to retain HS2 unsync vif even after mgmt_tx completes */ -#define SLSI_HS2_UNSYNC_VIF_EXTRA_MSEC 1000 - -/* Increased wait duration to retain unsync vif for GO-Negotiated to complete - * due to delayed response or, to allow peer to retry GO-Negotiation - */ -#define SLSI_P2P_NEG_PROC_UNSYNC_VIF_RETAIN_DURATION 3000 - -/* Increased wait duration to send unset channel to Fw. - * This would increase the listen time. - */ -#define SLSI_P2P_UNSET_CHANNEL_EXTRA_MSEC 600 -/* Extra duration in addition to mgmt tx wait */ -#define SLSI_P2P_MGMT_TX_EXTRA_MSEC 100 - -#define SLSI_FORCE_SCHD_ACT_FRAME_MSEC 100 -#define SLSI_P2PGO_KEEP_ALIVE_PERIOD_SEC 10 -#define SLSI_P2PGC_CONN_TIMEOUT_MSEC 10000 - -/* P2P Public Action Frames */ -#define SLSI_P2P_PA_GO_NEG_REQ 0 -#define SLSI_P2P_PA_GO_NEG_RSP 1 -#define SLSI_P2P_PA_GO_NEG_CFM 2 -#define SLSI_P2P_PA_INV_REQ 3 -#define SLSI_P2P_PA_INV_RSP 4 -#define SLSI_P2P_PA_DEV_DISC_REQ 5 -#define SLSI_P2P_PA_DEV_DISC_RSP 6 -#define SLSI_P2P_PA_PROV_DISC_REQ 7 -#define SLSI_P2P_PA_PROV_DISC_RSP 8 -#define SLSI_P2P_PA_INVALID 0xFF - -/* Service discovery public action frame types */ -#define SLSI_PA_GAS_INITIAL_REQ (10) -#define SLSI_PA_GAS_INITIAL_RSP (11) -#define SLSI_PA_GAS_COMEBACK_REQ (12) -#define SLSI_PA_GAS_COMEBACK_RSP (13) - -/*Radio Measurement action frames types */ -#define SLSI_RM_RADIO_MEASUREMENT_REQ (0) -#define SLSI_RM_RADIO_MEASUREMENT_REP (1) -#define SLSI_RM_LINK_MEASUREMENT_REQ (2) -#define SLSI_RM_LINK_MEASUREMENT_REP (3) -#define SLSI_RM_NEIGH_REP_REQ (4) -#define SLSI_RM_NEIGH_REP_RSP (5) - -#define SLSI_WNM_ACTION_FIELD_MIN (0) -#define SLSI_WNM_ACTION_FIELD_MAX (27) - -/* For service discovery action frames dummy subtype is used by setting the 7th bit */ -#define SLSI_PA_GAS_DUMMY_SUBTYPE_MASK 0x80 -#define SLSI_PA_GAS_INITIAL_REQ_SUBTYPE (SLSI_PA_GAS_INITIAL_REQ | SLSI_PA_GAS_DUMMY_SUBTYPE_MASK) -#define SLSI_PA_GAS_INITIAL_RSP_SUBTYPE (SLSI_PA_GAS_INITIAL_RSP | SLSI_PA_GAS_DUMMY_SUBTYPE_MASK) -#define SLSI_PA_GAS_COMEBACK_REQ_SUBTYPE (SLSI_PA_GAS_COMEBACK_REQ | SLSI_PA_GAS_DUMMY_SUBTYPE_MASK) -#define SLSI_PA_GAS_COMEBACK_RSP_SUBTYPE (SLSI_PA_GAS_COMEBACK_RSP | SLSI_PA_GAS_DUMMY_SUBTYPE_MASK) - -#define SLSI_P2P_STATUS_ATTR_ID 0 -#define SLSI_P2P_STATUS_CODE_SUCCESS 0 - -#define SLSI_ROAMING_CHANNEL_CACHE_TIMEOUT (5 * 60) - -#define SLSI_RX_SEQ_NUM_MASK 0xFFF -#define SLSI_RX_VIA_TDLS_LINK 0x8000 - -#define SET_ETHERTYPE_PATTERN_DESC(pd, ethertype) \ - pd.offset = 0x0C; \ - pd.mask_length = 2; \ - pd.mask[0] = 0xff; \ - pd.mask[1] = 0xff; \ - pd.pattern[0] = ethertype >> 8; \ - pd.pattern[1] = ethertype & 0xFF - -/* For checking DHCP frame */ -#define SLSI_IP_TYPE_UDP 0x11 -#define SLSI_IP_TYPE_OFFSET 23 -#define SLSI_IP_SOURCE_PORT_OFFSET 34 -#define SLSI_IP_DEST_PORT_OFFSET 36 -#define SLSI_DHCP_SERVER_PORT 67 -#define SLSI_DHCP_CLIENT_PORT 68 -#define SLSI_DNS_DEST_PORT 53 -#define SLSI_MDNS_DEST_PORT 5353 - -#define SLSI_DHCP_MSG_MAGIC_OFFSET 278 -#define SLSI_DHCP_OPTION 53 -#define SLSI_DHCP_MESSAGE_TYPE_DISCOVER 0x01 -#define SLSI_DHCP_MESSAGE_TYPE_OFFER 0x02 -#define SLSI_DHCP_MESSAGE_TYPE_REQUEST 0x03 -#define SLSI_DHCP_MESSAGE_TYPE_DECLINE 0x04 -#define SLSI_DHCP_MESSAGE_TYPE_ACK 0x05 -#define SLSI_DHCP_MESSAGE_TYPE_NAK 0x06 -#define SLSI_DHCP_MESSAGE_TYPE_RELEASE 0x07 -#define SLSI_DHCP_MESSAGE_TYPE_INFORM 0x08 -#define SLSI_DHCP_MESSAGE_TYPE_FORCERENEW 0x09 -#define SLSI_DHCP_MESSAGE_TYPE_INVALID 0x0A - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -#define SLSI_MAX_ARP_SEND_FRAME 8 -#endif -#define SLSI_ARP_SRC_IP_ADDR_OFFSET 14 -#define SLSI_ARP_DEST_IP_ADDR_OFFSET 24 -#define SLSI_IS_GRATUITOUS_ARP(frame) (!memcmp(&frame[SLSI_ARP_SRC_IP_ADDR_OFFSET],\ - &frame[SLSI_ARP_DEST_IP_ADDR_OFFSET], 4)) -#define SLSI_ARP_REPLY_OPCODE 2 -#define SLSI_ARP_REQUEST_OPCODE 1 -#define SLSI_ARP_OPCODE_OFFSET 6 - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 4, 0)) - #define WLAN_CATEGORY_WNM 10 -#endif - -enum slsi_dhcp_tx { - SLSI_TX_IS_NOT_DHCP, - SLSI_TX_IS_DHCP_SERVER, - SLSI_TX_IS_DHCP_CLIENT -}; - -enum slsi_fw_regulatory_rule_flags { - SLSI_REGULATORY_NO_IR = 1 << 0, - SLSI_REGULATORY_DFS = 1 << 1, - SLSI_REGULATORY_NO_OFDM = 1 << 2, - SLSI_REGULATORY_NO_INDOOR = 1 << 3, - SLSI_REGULATORY_NO_OUTDOOR = 1 << 4 -}; - -enum slsi_sta_conn_state { - SLSI_STA_CONN_STATE_DISCONNECTED = 0, - SLSI_STA_CONN_STATE_CONNECTING = 1, - SLSI_STA_CONN_STATE_DOING_KEY_CONFIG = 2, - SLSI_STA_CONN_STATE_CONNECTED = 3 -}; - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) -static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2) -{ - return !ether_addr_equal(addr1, addr2); -} -#endif - -/** - * Peer record handling: - * Records are created/destroyed by the control path eg cfg80211 connect or - * when handling a MLME-CONNECT-IND when the VIA is an AP. - * - * However peer records are also currently accessed from the data path in both - * Tx and Rx directions: - * Tx - to determine the queueset - * Rx - for routing received packets back out to peers - * - * So the interactions required for the data path: - * 1. can NOT block - * 2. needs to be as quick as possible - */ -static inline struct slsi_peer *slsi_get_peer_from_mac(struct slsi_dev *sdev, struct net_device *dev, const u8 *mac) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - (void)sdev; /* unused */ - - /* Accesses the peer records but doesn't block as called from the data path. - * MUST check the valid flag on the record before accessing any other data in the record. - * Records are static, so having obtained a pointer the pointer will remain valid - * it just maybe the data that it points to gets set to ZERO. - */ - - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - if (ndev_vif->sta.tdls_enabled) { - int i; - - for (i = 1; i < SLSI_TDLS_PEER_INDEX_MAX; i++) - if (ndev_vif->peer_sta_record[i] && ndev_vif->peer_sta_record[i]->valid && - compare_ether_addr(ndev_vif->peer_sta_record[i]->address, mac) == 0) - return ndev_vif->peer_sta_record[i]; - } - if (ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET] && ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET]->valid) - return ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET]; - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) { - int i = 0; - - for (i = 0; i < SLSI_PEER_INDEX_MAX; i++) - if (ndev_vif->peer_sta_record[i] && ndev_vif->peer_sta_record[i]->valid && - compare_ether_addr(ndev_vif->peer_sta_record[i]->address, mac) == 0) - return ndev_vif->peer_sta_record[i]; - } - return NULL; -} - -static inline struct slsi_peer *slsi_get_peer_from_qs(struct slsi_dev *sdev, struct net_device *dev, u16 queueset) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - (void)sdev; /* unused */ - - if (!ndev_vif->peer_sta_record[queueset] || !ndev_vif->peer_sta_record[queueset]->valid) - return NULL; - - return ndev_vif->peer_sta_record[queueset]; -} - -static inline bool slsi_is_tdls_peer(struct net_device *dev, struct slsi_peer *peer) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - return (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && (peer->aid >= SLSI_TDLS_PEER_INDEX_MIN); -} - -static inline bool slsi_is_proxy_arp_supported_on_ap(struct sk_buff *assoc_resp_ie) -{ - const u8 *ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, assoc_resp_ie->data, assoc_resp_ie->len); - - if ((ie) && (ie[1] > 1)) - return ie[3] & 0x10; /*0: eid, 1: len; 3: proxy arp is 12th bit*/ - - return 0; -} - -static inline int slsi_cache_ies(const u8 *src_ie, size_t src_ie_len, u8 **dest_ie, size_t *dest_ie_len) -{ - *dest_ie = kmalloc(src_ie_len, GFP_KERNEL); - if (*dest_ie == NULL) - return -ENOMEM; - - memcpy(*dest_ie, src_ie, src_ie_len); - *dest_ie_len = src_ie_len; - - return 0; -} - -static inline void slsi_clear_cached_ies(u8 **ie, size_t *ie_len) -{ - if (*ie_len != 0) - kfree(*ie); - *ie = NULL; - *ie_len = 0; -} - -/* P2P Public Action frame subtype in text format for debug purposes */ -static inline char *slsi_p2p_pa_subtype_text(int subtype) -{ - switch (subtype) { - case SLSI_P2P_PA_GO_NEG_REQ: - return "GO_NEG_REQ"; - case SLSI_P2P_PA_GO_NEG_RSP: - return "GO_NEG_RSP"; - case SLSI_P2P_PA_GO_NEG_CFM: - return "GO_NEG_CFM"; - case SLSI_P2P_PA_INV_REQ: - return "INV_REQ"; - case SLSI_P2P_PA_INV_RSP: - return "INV_RSP"; - case SLSI_P2P_PA_DEV_DISC_REQ: - return "DEV_DISC_REQ"; - case SLSI_P2P_PA_DEV_DISC_RSP: - return "DEV_DISC_RSP"; - case SLSI_P2P_PA_PROV_DISC_REQ: - return "PROV_DISC_REQ"; - case SLSI_P2P_PA_PROV_DISC_RSP: - return "PROV_DISC_RSP"; - case SLSI_PA_GAS_INITIAL_REQ_SUBTYPE: - return "GAS_INITIAL_REQUEST"; - case SLSI_PA_GAS_INITIAL_RSP_SUBTYPE: - return "GAS_INITIAL_RESPONSE"; - case SLSI_PA_GAS_COMEBACK_REQ_SUBTYPE: - return "GAS_COMEBACK_REQUEST"; - case SLSI_PA_GAS_COMEBACK_RSP_SUBTYPE: - return "GAS_COMEBACK_RESPONSE"; - case SLSI_P2P_PA_INVALID: - return "PA_INVALID"; - default: - return "UNKNOWN"; - } -} - -/* Cookie generation and assignment for user space ROC and mgmt_tx request from supplicant */ -static inline void slsi_assign_cookie_id(u64 *cookie, u64 *counter) -{ - (*cookie) = ++(*counter); - if ((*cookie) == 0) - (*cookie) = ++(*counter); -} - -/* Update P2P Probe Response IEs in driver */ -static inline void slsi_unsync_vif_set_probe_rsp_ie(struct netdev_vif *ndev_vif, u8 *ies, size_t ies_len) -{ - if (ndev_vif->unsync.probe_rsp_ies_len) - kfree(ndev_vif->unsync.probe_rsp_ies); - ndev_vif->unsync.probe_rsp_ies = ies; - ndev_vif->unsync.probe_rsp_ies_len = ies_len; -} - -/* Set management frame tx data of vif */ -static inline int slsi_set_mgmt_tx_data(struct netdev_vif *ndev_vif, u64 cookie, u16 host_tag, const u8 *buf, size_t buf_len) -{ - u8 *tx_frame = NULL; - - if (buf_len != 0) { - tx_frame = kmalloc(buf_len, GFP_KERNEL); - if (!tx_frame) { - SLSI_NET_ERR(ndev_vif->wdev.netdev, "FAILED to allocate memory for Tx frame\n"); - return -ENOMEM; - } - SLSI_NET_DBG3(ndev_vif->wdev.netdev, SLSI_CFG80211, "Copy buffer for tx_status\n"); - memcpy(tx_frame, buf, buf_len); - } else if (ndev_vif->mgmt_tx_data.buf) { - SLSI_NET_DBG3(ndev_vif->wdev.netdev, SLSI_CFG80211, "Free buffer of tx_status\n"); - kfree(ndev_vif->mgmt_tx_data.buf); - } - - ndev_vif->mgmt_tx_data.cookie = cookie; - ndev_vif->mgmt_tx_data.host_tag = host_tag; - ndev_vif->mgmt_tx_data.buf = tx_frame; - ndev_vif->mgmt_tx_data.buf_len = buf_len; - - return 0; -} - -/** - * Handler to queue P2P unsync vif deletion work. - */ -static inline void slsi_p2p_queue_unsync_vif_del_work(struct netdev_vif *ndev_vif, unsigned int delay) -{ - cancel_delayed_work(&ndev_vif->unsync.del_vif_work); - queue_delayed_work(ndev_vif->sdev->device_wq, &ndev_vif->unsync.del_vif_work, msecs_to_jiffies(delay)); -} - -/* Update the new state for P2P. Also log the state change for debug purpose */ -#define SLSI_P2P_STATE_CHANGE(sdev, next_state) \ - do { \ - SLSI_DBG1(sdev, SLSI_CFG80211, "P2P state change: %s -> %s\n", slsi_p2p_state_text(sdev->p2p_state), slsi_p2p_state_text(next_state)); \ - sdev->p2p_state = next_state; \ - } while (0) - -void slsi_purge_scan_results(struct netdev_vif *ndev_vif, u16 scan_id); -void slsi_purge_scan_results_locked(struct netdev_vif *ndev_vif, u16 scan_id); -struct sk_buff *slsi_dequeue_cached_scan_result(struct slsi_scan *scan, int *count); -void slsi_get_hw_mac_address(struct slsi_dev *sdev, u8 *addr); -int slsi_start(struct slsi_dev *sdev); -int slsi_start_monitor_mode(struct slsi_dev *sdev, struct net_device *dev); -void slsi_stop_net_dev(struct slsi_dev *sdev, struct net_device *dev); -void slsi_stop(struct slsi_dev *sdev); -void slsi_stop_locked(struct slsi_dev *sdev); -struct slsi_peer *slsi_peer_add(struct slsi_dev *sdev, struct net_device *dev, u8 *peer_address, u16 aid); -void slsi_peer_update_assoc_req(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, struct sk_buff *skb); -void slsi_peer_update_assoc_rsp(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, struct sk_buff *skb); -void slsi_peer_reset_stats(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer); -int slsi_peer_remove(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer); -int slsi_ps_port_control(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, enum slsi_sta_conn_state s); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) -int slsi_del_station(struct wiphy *wiphy, struct net_device *dev, - struct station_del_parameters *del_params); -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) -int slsi_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac); -#else -int slsi_del_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac); -#endif - -int slsi_sta_ieee80211_mode(struct net_device *dev, u16 current_bss_channel_frequency); -int slsi_vif_activated(struct slsi_dev *sdev, struct net_device *dev); -void slsi_vif_deactivated(struct slsi_dev *sdev, struct net_device *dev); -int slsi_handle_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *peer_address, u16 reason, - u8 *disassoc_rsp_ie, int disassoc_rsp_ie_len); -int slsi_band_update(struct slsi_dev *sdev, int band); -int slsi_ip_address_changed(struct slsi_dev *sdev, struct net_device *dev, __be32 ipaddress); -int slsi_send_gratuitous_arp(struct slsi_dev *sdev, struct net_device *dev); -struct ieee80211_channel *slsi_find_scan_channel(struct slsi_dev *sdev, struct ieee80211_mgmt *mgmt, size_t mgmt_len, u16 freq); -int slsi_auto_chan_select_scan(struct slsi_dev *sdev, int chan_count, struct ieee80211_channel *channels[]); -int slsi_set_uint_mib(struct slsi_dev *dev, struct net_device *ndev, u16 psid, int value); -int slsi_update_regd_rules(struct slsi_dev *sdev, bool country_check); -int slsi_set_boost(struct slsi_dev *sdev, struct net_device *dev); -int slsi_p2p_init(struct slsi_dev *sdev, struct netdev_vif *ndev_vif); -void slsi_p2p_deinit(struct slsi_dev *sdev, struct netdev_vif *ndev_vif); -int slsi_p2p_vif_activate(struct slsi_dev *sdev, struct net_device *dev, struct ieee80211_channel *chan, u16 duration, bool set_probe_rsp_ies); -void slsi_p2p_vif_deactivate(struct slsi_dev *sdev, struct net_device *dev, bool hw_available); -void slsi_p2p_group_start_remove_unsync_vif(struct slsi_dev *sdev); -int slsi_p2p_dev_probe_rsp_ie(struct slsi_dev *sdev, struct net_device *dev, u8 *probe_rsp_ie, size_t probe_rsp_ie_len); -int slsi_p2p_dev_null_ies(struct slsi_dev *sdev, struct net_device *dev); -int slsi_p2p_get_public_action_subtype(const struct ieee80211_mgmt *mgmt); -int slsi_p2p_get_go_neg_rsp_status(struct net_device *dev, const struct ieee80211_mgmt *mgmt); -u8 slsi_p2p_get_exp_peer_frame_subtype(u8 subtype); -int slsi_send_txq_params(struct slsi_dev *sdev, struct net_device *ndev); -void slsi_abort_sta_scan(struct slsi_dev *sdev); -int slsi_is_dhcp_packet(u8 *data); - -#ifdef CONFIG_SCSC_WLAN_PRIORITISE_IMP_FRAMES -int slsi_is_dns_packet(u8 *data); -int slsi_is_mdns_packet(u8 *data); -int slsi_is_tcp_sync_packet(struct net_device *dev, struct sk_buff *skb); -#endif - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER -int slsi_set_enhanced_pkt_filter(struct net_device *dev, u8 pkt_filter_enable); -#endif -#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER -int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled); -#endif -void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *dev); -int slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev); -int slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev); -int slsi_ap_prepare_add_info_ies(struct netdev_vif *ndev_vif, const u8 *ies, size_t ies_len); -int slsi_set_mib_roam(struct slsi_dev *dev, struct net_device *ndev, u16 psid, int value); -#ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA -int slsi_set_mib_preferred_antenna(struct slsi_dev *dev, u16 value); -#endif -void slsi_reset_throughput_stats(struct net_device *dev); -int slsi_set_mib_rssi_boost(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int index, int boost); -#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE -int slsi_set_mib_soft_roaming_enabled(struct slsi_dev *sdev, struct net_device *dev, bool enable); -#endif -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -int slsi_read_enhanced_arp_rx_count_by_lower_mac(struct slsi_dev *sdev, struct net_device *dev, u16 psid); -void slsi_fill_enhanced_arp_out_of_order_drop_counter(struct netdev_vif *ndev_vif, - struct sk_buff *skb); -#endif -void slsi_modify_ies_on_channel_switch(struct net_device *dev, struct cfg80211_ap_settings *settings, - u8 *ds_params_ie, u8 *ht_operation_ie, struct ieee80211_mgmt *mgmt, - u16 beacon_ie_head_len); -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -bool slsi_if_valid_wifi_sharing_channel(struct slsi_dev *sdev, int freq); -void slsi_extract_valid_wifi_sharing_channels(struct slsi_dev *sdev); -int slsi_check_if_non_indoor_non_dfs_channel(struct slsi_dev *sdev, int freq); -int slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *settings, struct slsi_dev *sdev, - int *wifi_sharing_channel_switched); -int slsi_set_mib_wifi_sharing_5ghz_channel(struct slsi_dev *sdev, u16 psid, int value, - int offset, int readbyte, char *arg); -int slsi_get_byte_position(int bit); -int slsi_check_if_channel_restricted_already(struct slsi_dev *sdev, int channel); -#endif -struct net_device *slsi_dynamic_interface_create(struct wiphy *wiphy, - const char *name, - enum nl80211_iftype type, - struct vif_params *params); -int slsi_get_mib_roam(struct slsi_dev *sdev, u16 psid, int *mib_value); -void slsi_roam_channel_cache_add(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_roam_channel_cache_prune(struct net_device *dev, int seconds); -int slsi_roaming_scan_configure_channels(struct slsi_dev *sdev, struct net_device *dev, const u8 *ssid, u8 *channels); -int slsi_send_max_transmit_msdu_lifetime(struct slsi_dev *dev, struct net_device *ndev, u32 msdu_lifetime); -int slsi_read_max_transmit_msdu_lifetime(struct slsi_dev *dev, struct net_device *ndev, u32 *msdu_lifetime); -int slsi_read_unifi_countrylist(struct slsi_dev *sdev, u16 psid); -int slsi_read_default_country(struct slsi_dev *sdev, u8 *alpha2, u16 index); -int slsi_read_disconnect_ind_timeout(struct slsi_dev *sdev, u16 psid); -int slsi_read_regulatory_rules(struct slsi_dev *sdev, struct slsi_802_11d_reg_domain *domain_info, const char *alpha2); -int slsi_send_acs_event(struct slsi_dev *sdev, struct slsi_acs_selected_channels acs_selected_channels); -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION -int slsi_set_mac_randomisation_mask(struct slsi_dev *sdev, u8 *mac_address_mask); -#endif -int slsi_set_country_update_regd(struct slsi_dev *sdev, const char *alpha2_code, int size); -void slsi_clear_offchannel_data(struct slsi_dev *sdev, bool acquire_lock); -int slsi_wlan_unsync_vif_activate(struct slsi_dev *sdev, struct net_device *dev, - struct ieee80211_channel *chan, u16 duration); -void slsi_wlan_unsync_vif_deactivate(struct slsi_dev *sdev, struct net_device *devbool, bool hw_available); -int slsi_is_wes_action_frame(const struct ieee80211_mgmt *mgmt); -void slsi_scan_ind_timeout_handle(struct work_struct *work); -void slsi_vif_cleanup(struct slsi_dev *sdev, struct net_device *dev, bool hw_available); -void slsi_scan_cleanup(struct slsi_dev *sdev, struct net_device *dev); -void slsi_dump_stats(struct net_device *dev); -int slsi_send_hanged_vendor_event(struct slsi_dev *sdev, u16 scsc_panic_code); -void slsi_update_supported_channels_regd_flags(struct slsi_dev *sdev); -#ifdef CONFIG_SCSC_WLAN_HANG_TEST -int slsi_test_send_hanged_vendor_event(struct net_device *dev); -#endif -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -int slsi_send_forward_beacon_vendor_event(struct slsi_dev *sdev, const u8 *ssid, const int ssid_len, const u8 *bssid, - u8 channel, const u16 beacon_int, const u64 timestamp, const u64 sys_time); -int slsi_send_forward_beacon_abort_vendor_event(struct slsi_dev *sdev, u16 reason_code); -#endif -void slsi_wlan_dump_public_action_subtype(struct slsi_dev *sdev, struct ieee80211_mgmt *mgmt, bool tx); -void slsi_reset_channel_flags(struct slsi_dev *sdev); - -/* Sysfs based mac address override */ -void slsi_create_sysfs_macaddr(void); -void slsi_destroy_sysfs_macaddr(void); -int slsi_find_chan_idx(u16 chan, u8 hw_mode); -#ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS -int slsi_set_num_antennas(struct net_device *dev, const u16 num_of_antennas); -#endif -int slsi_set_latency_mode(struct net_device *dev, int latency_mode, int cmd_len); -#endif /*__SLSI_MGT_H__*/ diff --git a/drivers/net/wireless/scsc/mib.c b/drivers/net/wireless/scsc/mib.c deleted file mode 100755 index 10d16a4ac493..000000000000 --- a/drivers/net/wireless/scsc/mib.c +++ /dev/null @@ -1,598 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd and its Licensors. - * All rights reserved. - * - *****************************************************************************/ - -#include "const.h" -#include "mib.h" -#include "debug.h" - -#define SLSI_MIB_MORE_MASK 0x80 -#define SLSI_MIB_SIGN_MASK 0x40 -#define SLSI_MIB_TYPE_MASK 0x20 -#define SLSI_MIB_LENGTH_MASK 0x1FU -/** - * @brief - * Append a buffer to an existing buffer. - * This will kmalloc a new buffer and kfree the old one - */ -void slsi_mib_buf_append(struct slsi_mib_data *dst, size_t buffer_length, u8 *buffer) -{ - u8 *new_buffer = kmalloc(dst->dataLength + buffer_length, GFP_KERNEL); - - if (!new_buffer) { - SLSI_ERR_NODEV("kmalloc(%d) failed\n", (int)(dst->dataLength + buffer_length)); - return; - } - - memcpy(new_buffer, dst->data, dst->dataLength); - memcpy(&new_buffer[dst->dataLength], buffer, buffer_length); - - dst->dataLength += (u16)buffer_length; - kfree(dst->data); - dst->data = new_buffer; -} - -size_t slsi_mib_encode_uint32(u8 *buffer, u32 value) -{ - u8 i; - u8 write_count = 0; - - if (value < 64) { - buffer[0] = (u8)value; - return 1; - } - - /* Encode the Integer - * 0xABFF0055 = [0xAB, 0xFF, 0x00, 0x55] - * 0xAB0055 = [0xAB, 0x00, 0x55] - * 0xAB55 = [0xAB, 0x55] - * 0x55 = [0x55] - */ - for (i = 0; i < 4; i++) { - u8 byte_value = (value & 0xFF000000) >> 24; - - if (byte_value || write_count) { - buffer[1 + write_count] = byte_value; - write_count++; - } - value = value << 8; - } - - /* vldata Length | more bit */ - buffer[0] = write_count | SLSI_MIB_MORE_MASK; - - return 1 + write_count; -} - -size_t slsi_mib_encode_int32(u8 *buffer, s32 signed_value) -{ - u8 i; - u8 write_count = 0; - u32 value = (u32)signed_value; - - if (!(value & 0x10000000)) - /* just use the Unsigned Encoder */ - return slsi_mib_encode_uint32(buffer, value); - - if (signed_value >= -64) { - buffer[0] = (u8)value & 0x7F; /* vldata Length | more bit */ - return 1; - } - - /* Encode the Negative Integer */ - for (i = 0; i < 4; i++) { - u8 byte_value = (value & 0xFF000000) >> 24; - - if (!((byte_value == 0xFF) && (value & 0x800000)) || write_count) { - buffer[1 + write_count] = byte_value; - write_count++; - } - value = value << 8; - } - /* vldata Length | more bit | sign bit*/ - buffer[0] = write_count | SLSI_MIB_MORE_MASK | SLSI_MIB_SIGN_MASK; - - return 1 + write_count; -} - -size_t slsi_mib_encode_octet_str(u8 *buffer, struct slsi_mib_data *octet_value) -{ - u8 i; - u8 write_count = 0; - size_t length = octet_value->dataLength; - - /* Encode the Length (Up to 4 bytes 32 bits worth) - * 0xABFF0000 = [0xAB, 0xFF, 0x00, 0x00] - * 0xAB0000 = [0xAB, 0x00, 0x00] - * 0xAB00 = [0xAB, 0x00] - * 0x00 = [0x00] - */ - for (i = 0; i < 3; i++) { - u8 byte_value = (length & 0xFF000000) >> 24; - - if (byte_value || write_count) { - buffer[1 + write_count] = byte_value; - write_count++; - } - length = length << 8; - } - - buffer[0] = (1 + write_count) | SLSI_MIB_MORE_MASK | SLSI_MIB_TYPE_MASK; - buffer[1 + write_count] = octet_value->dataLength & 0xFF; - memcpy(&buffer[2 + write_count], octet_value->data, octet_value->dataLength); - - return 2U + write_count + octet_value->dataLength; -} - -size_t slsi_mib_decode_uint32(u8 *buffer, u32 *value) -{ - size_t i; - u32 v = 0; - size_t length = buffer[0] & SLSI_MIB_LENGTH_MASK; - - if (!(buffer[0] & SLSI_MIB_MORE_MASK)) { - *value = buffer[0] & 0x7F; - return 1; - } - - for (i = 0; i < length; i++) { - v = (v << 8); - v |= buffer[1 + i]; - } - - *value = v; - - return 1 + length; -} - -size_t slsi_mib_decodeUint64(u8 *buffer, u64 *value) -{ - size_t i; - u64 v = 0; - size_t length = buffer[0] & SLSI_MIB_LENGTH_MASK; - - if (!(buffer[0] & SLSI_MIB_MORE_MASK)) { - *value = buffer[0] & 0x7F; - return 1; - } - - for (i = 0; i < length; i++) { - v = (v << 8); - v |= buffer[1 + i]; - } - - *value = v; - - return 1 + length; -} - -size_t slsi_mib_decodeInt32(u8 *buffer, s32 *value) -{ - size_t i; - u32 v = 0xFFFFFFFF; - size_t length = buffer[0] & SLSI_MIB_LENGTH_MASK; - - if (!(buffer[0] & SLSI_MIB_SIGN_MASK)) - /* just use the Unsigned Decoder */ - return slsi_mib_decode_uint32(buffer, (u32 *)value); - - if (!(buffer[0] & SLSI_MIB_MORE_MASK)) { - *value = (s32)(0xFFFFFF80 | buffer[0]); - return 1; - } - - for (i = 0; i < length; i++) { - v = (v << 8); - v |= buffer[1 + i]; - } - - *value = (s32)v; - - return 1 + length; -} - -size_t slsi_mib_decodeInt64(u8 *buffer, s64 *value) -{ - size_t i; - u64 v = 0xFFFFFFFFFFFFFFFFULL; - size_t length = buffer[0] & SLSI_MIB_LENGTH_MASK; - - if (!(buffer[0] & SLSI_MIB_SIGN_MASK)) - /* just use the Unsigned Decoder */ - return slsi_mib_decodeUint64(buffer, (u64 *)value); - - if (!(buffer[0] & SLSI_MIB_MORE_MASK)) { - *value = (s64)(0xFFFFFFFFFFFFFF80ULL | buffer[0]); - return 1; - } - - for (i = 0; i < length; i++) { - v = (v << 8); - v |= buffer[1 + i]; - } - - *value = (s64)v; - - return 1 + length; -} - -/* Just references the oid in the existing buffer. No new memory is allcated */ -size_t slsi_mib_decode_octet_str(u8 *buffer, struct slsi_mib_data *octet_value) -{ - size_t i; - u32 oid_length_value = 0; - size_t length = buffer[0] & SLSI_MIB_LENGTH_MASK; - - for (i = 0; i < length; i++) { - oid_length_value = (oid_length_value << 8); - oid_length_value |= buffer[1 + i]; - } - - octet_value->dataLength = oid_length_value; - octet_value->data = NULL; - if (oid_length_value) - octet_value->data = &buffer[1 + length]; - - return 1 + length + oid_length_value; -} - -static u8 slsi_mib_decode_type_length(u8 *buffer, size_t *length) -{ - *length = 1; - if (buffer[0] & SLSI_MIB_MORE_MASK) - *length = buffer[0] & SLSI_MIB_LENGTH_MASK; - - if (buffer[0] & SLSI_MIB_SIGN_MASK) - return SLSI_MIB_TYPE_INT; - - if ((buffer[0] & SLSI_MIB_MORE_MASK) && - (buffer[0] & SLSI_MIB_TYPE_MASK)) { - size_t i; - size_t oid_length_value = 0; - - for (i = 0; i < *length; i++) { - oid_length_value = (oid_length_value << 8); - oid_length_value |= buffer[1 + i]; - } - *length += oid_length_value; - return SLSI_MIB_TYPE_OCTET; - } - return SLSI_MIB_TYPE_UINT; -} - -static size_t slsi_mib_encode_psid_indexs(u8 *buffer, const struct slsi_mib_get_entry *value) -{ - size_t i; - - SLSI_U16_TO_BUFF_LE(value->psid, &buffer[0]); - buffer[2] = 0; - buffer[3] = 0; - for (i = 0; i < SLSI_MIB_MAX_INDEXES && value->index[i] != 0; i++) - buffer[2] += (u8)slsi_mib_encode_uint32(&buffer[4 + buffer[2]], value->index[i]); - - if (buffer[2] % 2 == 1) { - /* Add a padding byte "0x00" to the encoded buffer. The Length - * value is NOT updated to account for this pad value. If the - * length is an Odd number the Pad values MUST be there if it - * is Even it will not be. - */ - buffer[4 + buffer[2]] = 0x00; - return 5 + buffer[2]; - } - - return 4 + buffer[2]; -} - -u16 slsi_mib_encode(struct slsi_mib_data *buffer, struct slsi_mib_entry *value) -{ - size_t i; - size_t required_size = 5U + (5U * SLSI_MIB_MAX_INDEXES) + - (value->value.type == SLSI_MIB_TYPE_OCTET ? value->value.u.octetValue.dataLength : 5U); - - size_t encoded_length = 4; - - u8 *tmp_buffer = kmalloc(required_size, GFP_KERNEL); - - if (!tmp_buffer) { - SLSI_ERR_NODEV("kmalloc(%d) failed\n", (int)required_size); - return SLSI_MIB_STATUS_FAILURE; - } - - SLSI_U16_TO_BUFF_LE(value->psid, &tmp_buffer[0]); - tmp_buffer[2] = 0; - tmp_buffer[3] = 0; - for (i = 0; i < SLSI_MIB_MAX_INDEXES && value->index[i] != 0; i++) - tmp_buffer[2] += (u8)slsi_mib_encode_uint32(&tmp_buffer[4 + tmp_buffer[2]], value->index[i]); - encoded_length += tmp_buffer[2]; - - switch (value->value.type) { - case SLSI_MIB_TYPE_UINT: - encoded_length += slsi_mib_encode_uint32(&tmp_buffer[encoded_length], value->value.u.uintValue); - break; - case SLSI_MIB_TYPE_INT: - encoded_length += slsi_mib_encode_int32(&tmp_buffer[encoded_length], value->value.u.intValue); - break; - case SLSI_MIB_TYPE_OCTET: - encoded_length += slsi_mib_encode_octet_str(&tmp_buffer[encoded_length], &value->value.u.octetValue); - break; - case SLSI_MIB_TYPE_BOOL: - encoded_length += slsi_mib_encode_uint32(&tmp_buffer[encoded_length], value->value.u.boolValue ? true : false); - break; - case SLSI_MIB_TYPE_NONE: - break; - default: - SLSI_WARN_NODEV("Invalid Type:%d requested\n", value->value.type); - kfree(tmp_buffer); - return SLSI_MIB_STATUS_FAILURE; - } - - SLSI_U16_TO_BUFF_LE(encoded_length - 4, &tmp_buffer[2]); /* length */ - - if (encoded_length % 2 == 1) { - /* Add a padding byte "0x00" to the encoded buffer. The Length - * value is NOT updated to account for this pad value. If the - * length is an Odd number the Pad values MUST be there if it - * is Even it will not be. - */ - tmp_buffer[encoded_length] = 0x00; - encoded_length++; - } - - slsi_mib_buf_append(buffer, encoded_length, tmp_buffer); - kfree(tmp_buffer); - - return SLSI_MIB_STATUS_SUCCESS; -} - -size_t slsi_mib_decode(struct slsi_mib_data *data, struct slsi_mib_entry *value) -{ - u8 *buffer = data->data; - u32 buffer_length = data->dataLength; - size_t index_count = 0; - size_t length; - size_t decoded_length = 4; - - memset(value, 0x00, sizeof(struct slsi_mib_entry)); - - if (buffer_length < 4) { - SLSI_WARN_NODEV("Mib Decode Length:%d Must be greater than 4\n", buffer_length); - return 0; - } - - if (!buffer) - return 0; - - length = SLSI_BUFF_LE_TO_U16(&buffer[2]); - - if (buffer_length < decoded_length + length) { - SLSI_ERR_NODEV("Mib Buffer Length:%d Must be >= than decoded length:%d\n", buffer_length, (int)(decoded_length + length)); - return 0; - } - - value->psid = SLSI_BUFF_LE_TO_U16(buffer); - value->value.type = SLSI_MIB_TYPE_NONE; - - while (decoded_length < 4 + length) { - size_t next_value_length; - u8 type = slsi_mib_decode_type_length(&buffer[decoded_length], &next_value_length); - - if (buffer_length < decoded_length + next_value_length) { - SLSI_ERR_NODEV("Mib Buffer Length:%d Must be >= than decoded length:%d\n", buffer_length, (int)(decoded_length + next_value_length)); - memset(value, 0x00, sizeof(struct slsi_mib_entry)); - return 0; - } - - switch (type) { - case SLSI_MIB_TYPE_UINT: - { - u32 v; - - decoded_length += slsi_mib_decode_uint32(&buffer[decoded_length], &v); - /* If this is that last value then it is the "unitValue" - * if other values follow it is an Index Value - */ - if ((decoded_length < 4 + length) && - (index_count != SLSI_MIB_MAX_INDEXES)) { - value->index[index_count] = (u16)v; - index_count++; - } else { - value->value.type = type; - value->value.u.uintValue = v; - if (decoded_length != 4 + length) - SLSI_WARN_NODEV("Uint Decode length:%d != expected:%d\n", (u32)decoded_length, (u32)(4 + length)); - } - break; - } - case SLSI_MIB_TYPE_INT: - value->value.type = type; - decoded_length += slsi_mib_decodeInt32(&buffer[decoded_length], &value->value.u.intValue); - if (decoded_length != 4 + length) - SLSI_WARN_NODEV("Int Decode length:%d != expected:%d\n", (u32)decoded_length, (u32)(4 + length)); - break; - case SLSI_MIB_TYPE_OCTET: - value->value.type = type; - decoded_length += slsi_mib_decode_octet_str(&buffer[decoded_length], &value->value.u.octetValue); - if (decoded_length != 4 + length) - SLSI_WARN_NODEV("Octet Decode length:%d != expected:%d\n", (u32)decoded_length, (u32)(4 + length)); - break; - default: - SLSI_ERR_NODEV("Invalid MIB data type(%d). Possible mbulk corruption\n", type); - memset(value, 0x00, sizeof(struct slsi_mib_entry)); - value->value.type = SLSI_MIB_TYPE_NONE; - return 0; - } - } - if (length % 2 == 1) { - /* Remove the padding byte "0x00" in the encoded buffer. - * The Length value does NOT account for this pad value - * If the length is an Odd number the Pad values MUST be - * there if it is Even it will not be. - */ - if (buffer[decoded_length] != 0x00) - SLSI_WARN_NODEV("psid:0x%.4X Padding Not Detected\n", value->psid); - length++; - } - return 4 + length; -} - -int slsi_mib_encode_get_list(struct slsi_mib_data *buffer, u16 psids_length, const struct slsi_mib_get_entry *psids) -{ - size_t i; - - buffer->dataLength = 0; - /* 13 Bytes per get will be loads of space for the max 3 indexes */ - buffer->data = kmalloc((u32)(psids_length * 13), GFP_KERNEL); - if (!buffer->data) { - SLSI_ERR_NODEV("kmalloc(%d) failed\n", psids_length * 13); - return SLSI_MIB_STATUS_OUT_OF_MEMORY; - } - for (i = 0; i < psids_length; i++) - buffer->dataLength += (u16)slsi_mib_encode_psid_indexs(&buffer->data[buffer->dataLength], &psids[i]); - - return SLSI_MIB_STATUS_SUCCESS; -} - -void slsi_mib_encode_get(struct slsi_mib_data *buffer, u16 psid, u16 idx) -{ - /* 13 Bytes per get will be loads of space for the max 3 indexes */ - size_t size; - u8 tmp_buffer[13]; - struct slsi_mib_get_entry entry; - - memset(&entry, 0x00, sizeof(struct slsi_mib_get_entry)); - entry.psid = psid; - entry.index[0] = idx; - size = slsi_mib_encode_psid_indexs(tmp_buffer, &entry); - slsi_mib_buf_append(buffer, size, tmp_buffer); -} - -u8 *slsi_mib_find(struct slsi_mib_data *buffer, const struct slsi_mib_get_entry *entry) -{ - size_t buffer_length = buffer->dataLength; - u8 *buff = buffer->data; - - if (buffer_length % 2 == 1) { - SLSI_WARN_NODEV("buffer_length(%d) %% 2 != 0 (Invalid Mib data Detected)\n", (int)buffer_length); - return NULL; - } - while (buffer_length >= 4) { - u16 psid = SLSI_BUFF_LE_TO_U16(buff); - size_t length = 4U + SLSI_BUFF_LE_TO_U16(&buff[2]); - - if (entry->psid == psid) { - size_t i; - u32 idx; - size_t bytes_read = 0; - - for (i = 0; i < SLSI_MIB_MAX_INDEXES; i++) { - if (!entry->index[i]) - return buff; - bytes_read = slsi_mib_decode_uint32(&buff[4 + bytes_read], &idx); - if (entry->index[i] != idx) - break; - } - if (i == SLSI_MIB_MAX_INDEXES) - return buff; - } - if (length % 2 == 1) - /* Remove the padding byte "0x00" in the encoded buffer. - * The Length value does NOT account for this pad value - * If the length is an Odd number the Pad values MUST be - * there if it is Even it will not be. - */ - length++; - - buff += length; - buffer_length -= length; - } - - return NULL; -} - -struct slsi_mib_value *slsi_mib_decode_get_list(struct slsi_mib_data *buffer, u16 psids_length, const struct slsi_mib_get_entry *psids) -{ - struct slsi_mib_value *results = kmalloc_array((size_t)psids_length, sizeof(struct slsi_mib_value), GFP_KERNEL); - size_t i; - int len = 0; - char psids_not_found[150] = ""; - - if (!results) { - SLSI_ERR_NODEV("kmalloc(%d) failed\n", (int)(sizeof(struct slsi_mib_value) * psids_length)); - return results; - } - - for (i = 0; i < psids_length; i++) { - struct slsi_mib_entry value; - struct slsi_mib_data data; - - data.data = slsi_mib_find(buffer, &psids[i]); - if (data.data) { - data.dataLength = buffer->dataLength - (data.data - buffer->data); - value.psid = psids[i].psid; - memcpy(value.index, psids[i].index, sizeof(value.index)); - (void)slsi_mib_decode(&data, &value); - - results[i] = value.value; - } else { - len += snprintf(&psids_not_found[0] + len, 150 - len, "%d ", psids[i].psid); - results[i].type = SLSI_MIB_TYPE_NONE; - } - } - - if (len) - SLSI_ERR_NODEV("Could not find psid's: %s\n", psids_not_found); - - return results; -} - -u16 slsi_mib_encode_bool(struct slsi_mib_data *buffer, u16 psid, bool value, u16 idx) -{ - struct slsi_mib_entry v; - - memset(&v, 0x00, sizeof(struct slsi_mib_entry)); - v.psid = psid; - v.index[0] = idx; - v.value.type = SLSI_MIB_TYPE_BOOL; - v.value.u.boolValue = value; - return slsi_mib_encode(buffer, &v); -} - -u16 slsi_mib_encode_int(struct slsi_mib_data *buffer, u16 psid, s32 value, u16 idx) -{ - struct slsi_mib_entry v; - - memset(&v, 0x00, sizeof(struct slsi_mib_entry)); - v.psid = psid; - v.index[0] = idx; - v.value.type = SLSI_MIB_TYPE_INT; - v.value.u.intValue = value; - return slsi_mib_encode(buffer, &v); -} - -u16 slsi_mib_encode_uint(struct slsi_mib_data *buffer, u16 psid, u32 value, u16 idx) -{ - struct slsi_mib_entry v; - - memset(&v, 0x00, sizeof(struct slsi_mib_entry)); - v.psid = psid; - v.index[0] = idx; - v.value.type = SLSI_MIB_TYPE_UINT; - v.value.u.uintValue = value; - return slsi_mib_encode(buffer, &v); -} - -u16 slsi_mib_encode_octet(struct slsi_mib_data *buffer, u16 psid, size_t dataLength, const u8 *data, u16 idx) -{ - struct slsi_mib_entry v; - - memset(&v, 0x00, sizeof(struct slsi_mib_entry)); - v.psid = psid; - v.index[0] = idx; - v.value.type = SLSI_MIB_TYPE_OCTET; - v.value.u.octetValue.dataLength = (u32)dataLength; - v.value.u.octetValue.data = (u8 *)data; - return slsi_mib_encode(buffer, &v); -} diff --git a/drivers/net/wireless/scsc/mib.h b/drivers/net/wireless/scsc/mib.h deleted file mode 100755 index 5004b6e6aa21..000000000000 --- a/drivers/net/wireless/scsc/mib.h +++ /dev/null @@ -1,7801 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef SLSI_MIB_H__ -#define SLSI_MIB_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct slsi_mib_data { - u32 dataLength; - u8 *data; -}; - -#define SLSI_MIB_MAX_INDEXES 2U - -#define SLSI_MIB_TYPE_BOOL 0 -#define SLSI_MIB_TYPE_UINT 1 -#define SLSI_MIB_TYPE_INT 2 -#define SLSI_MIB_TYPE_OCTET 3U -#define SLSI_MIB_TYPE_NONE 4 - -struct slsi_mib_value { - u8 type; - union { - bool boolValue; - s32 intValue; - u32 uintValue; - struct slsi_mib_data octetValue; - } u; -}; - -struct slsi_mib_entry { - u16 psid; - u16 index[SLSI_MIB_MAX_INDEXES]; /* 0 = no Index */ - struct slsi_mib_value value; -}; - -struct slsi_mib_get_entry { - u16 psid; - u16 index[SLSI_MIB_MAX_INDEXES]; /* 0 = no Index */ -}; - -#define SLSI_MIB_STATUS_SUCCESS 0x0000 -#define SLSI_MIB_STATUS_UNKNOWN_PSID 0x0001 -#define SLSI_MIB_STATUS_INVALID_INDEX 0x0002 -#define SLSI_MIB_STATUS_OUT_OF_RANGE 0x0003 -#define SLSI_MIB_STATUS_WRITE_ONLY 0x0004 -#define SLSI_MIB_STATUS_READ_ONLY 0x0005 -#define SLSI_MIB_STATUS_UNKNOWN_INTERFACE_TAG 0x0006 -#define SLSI_MIB_STATUS_INVALID_NUMBER_OF_INDICES 0x0007 -#define SLSI_MIB_STATUS_ERROR 0x0008 -#define SLSI_MIB_STATUS_UNSUPPORTED_ON_INTERFACE 0x0009 -#define SLSI_MIB_STATUS_UNAVAILABLE 0x000A -#define SLSI_MIB_STATUS_NOT_FOUND 0x000B -#define SLSI_MIB_STATUS_INCOMPATIBLE 0x000C -#define SLSI_MIB_STATUS_OUT_OF_MEMORY 0x000D -#define SLSI_MIB_STATUS_TO_MANY_REQUESTED_VARIABLES 0x000E -#define SLSI_MIB_STATUS_NOT_TRIED 0x000F -#define SLSI_MIB_STATUS_FAILURE 0xFFFF - -/******************************************************************************* - * - * NAME - * slsi_mib_encode_get Functions - * - * DESCRIPTION - * For use when getting data from the Wifi Stack. - * These functions append the encoded data to the "buffer". - * - * index == 0 where there is no index required - * - * EXAMPLE - * { - * static const struct slsi_mib_get_entry getValues[] = { - * { PSID1, { 0, 0 } }, - * { PSID2, { 3, 0 } }, - * }; - * struct slsi_mib_data buffer; - * slsi_mib_encode_get_list(&buffer, - * sizeof(getValues) / sizeof(struct slsi_mib_get_entry), - * getValues); - * } - * or - * { - * struct slsi_mib_data buffer = {0, NULL}; - * slsi_mib_encode_get(&buffer, PSID1, 0); - * slsi_mib_encode_get(&buffer, PSID2, 3); - * } - * RETURN - * SlsiResult: See SLSI_MIB_STATUS_* - * - *******************************************************************************/ -void slsi_mib_encode_get(struct slsi_mib_data *buffer, u16 psid, u16 index); -int slsi_mib_encode_get_list(struct slsi_mib_data *buffer, u16 psidsLength, const struct slsi_mib_get_entry *psids); - -/******************************************************************************* - * - * NAME - * SlsiWifiMibdEncode Functions - * - * DESCRIPTION - * For use when getting data from the Wifi Stack. - * - * index == 0 where there is no index required - * - * EXAMPLE - * { - * static const struct slsi_mib_get_entry getValues[] = { - * { PSID1, { 0, 0 } }, - * { PSID2, { 3, 0 } }, - * }; - * struct slsi_mib_data buffer = rxMibData; # Buffer with encoded Mib Data - * - * getValues = slsi_mib_decode_get_list(&buffer, - * sizeof(getValues) / sizeof(struct slsi_mib_get_entry), - * getValues); - * - * print("PSID1 = %d\n", getValues[0].u.uintValue); - * print("PSID2.3 = %s\n", getValues[1].u.boolValue?"TRUE":"FALSE"); - * - * kfree(getValues); - * - * } - * or - * { - * u8* buffer = rxMibData; # Buffer with encoded Mib Data - * size_t offset=0; - * struct slsi_mib_entry value; - * - * offset += slsi_mib_decode(&buffer[offset], &value); - * print("PSID1 = %d\n", value.u.uintValue); - * - * offset += slsi_mib_decode(&buffer[offset], &value); - * print("PSID2.3 = %s\n", value.u.boolValue?"TRUE":"FALSE"); - * - * } - * - *******************************************************************************/ -size_t slsi_mib_decode(struct slsi_mib_data *buffer, struct slsi_mib_entry *value); -struct slsi_mib_value *slsi_mib_decode_get_list(struct slsi_mib_data *buffer, u16 psidsLength, const struct slsi_mib_get_entry *psids); - -/******************************************************************************* - * - * NAME - * slsi_mib_encode Functions - * - * DESCRIPTION - * For use when setting data in the Wifi Stack. - * These functions append the encoded data to the "buffer". - * - * index == 0 where there is no index required - * - * EXAMPLE - * { - * u8 octets[2] = {0x00, 0x01}; - * struct slsi_mib_data buffer = {0, NULL}; - * slsi_mib_encode_bool(&buffer, PSID1, TRUE, 0); # Boolean set with no index - * slsi_mib_encode_int(&buffer, PSID2, -1234, 1); # Signed Integer set with on index 1 - * slsi_mib_encode_uint(&buffer, PSID2, 1234, 3); # Unsigned Integer set with on index 3 - * slsi_mib_encode_octet(&buffer, PSID3, sizeof(octets), octets, 0); # Octet set with no index - * } - * or - * { - # Unsigned Integer set with on index 3 - # struct slsi_mib_data buffer = {0, NULL}; - # struct slsi_mib_entry value; - # value.psid = psid; - # value.index[0] = 3; - # value.index[1] = 0; - # value.value.type = SLSI_MIB_TYPE_UINT; - # value.value.u.uintValue = 1234; - # slsi_mib_encode(buffer, &value); - # } - # RETURN - # See SLSI_MIB_STATUS_* - # - *******************************************************************************/ -u16 slsi_mib_encode(struct slsi_mib_data *buffer, struct slsi_mib_entry *value); -u16 slsi_mib_encode_bool(struct slsi_mib_data *buffer, u16 psid, bool value, u16 index); -u16 slsi_mib_encode_int(struct slsi_mib_data *buffer, u16 psid, s32 value, u16 index); -u16 slsi_mib_encode_uint(struct slsi_mib_data *buffer, u16 psid, u32 value, u16 index); -u16 slsi_mib_encode_octet(struct slsi_mib_data *buffer, u16 psid, size_t dataLength, const u8 *data, u16 index); - -/******************************************************************************* - * - * NAME - * SlsiWifiMib Low level Encode/Decode functions - * - *******************************************************************************/ -size_t slsi_mib_encode_uint32(u8 *buffer, u32 value); -size_t slsi_mib_encode_int32(u8 *buffer, s32 signedValue); -size_t slsi_mib_encode_octet_str(u8 *buffer, struct slsi_mib_data *octetValue); - -size_t slsi_mib_decodeUint32(u8 *buffer, u32 *value); -size_t slsi_mib_decodeInt32(u8 *buffer, s32 *value); -size_t slsi_mib_decodeUint64(u8 *buffer, u64 *value); -size_t slsi_mib_decodeInt64(u8 *buffer, s64 *value); -size_t slsi_mib_decode_octet_str(u8 *buffer, struct slsi_mib_data *octetValue); - -/******************************************************************************* - * - * NAME - * SlsiWifiMib Helper Functions - * - *******************************************************************************/ - -/* Find a the offset to psid data in an encoded buffer - * { - * struct slsi_mib_data buffer = rxMibData; # Buffer with encoded Mib Data - * struct slsi_mib_get_entry value = {PSID1, {0x01, 0x00}}; # Find value for PSID1.1 - * u8* mibdata = slsi_mib_find(&buffer, &value); - * if(mibdata) {print("Mib Data for PSID1.1 Found\n"); - * } - */ -u8 *slsi_mib_find(struct slsi_mib_data *buffer, const struct slsi_mib_get_entry *entry); - -/* Append data to a Buffer */ -void slsi_mib_buf_append(struct slsi_mib_data *dst, size_t bufferLength, u8 *buffer); - -/******************************************************************************* - * - * PSID Definitions - * - *******************************************************************************/ - -/******************************************************************************* - * NAME : Dot11TdlsPeerUapsdIndicationWindow - * PSID : 53 (0x0035) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : beacon intervals - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1 - * DESCRIPTION : - * The minimum time after the last TPU SP, before a RAME_TPU_SP indication - * can be issued. - *******************************************************************************/ -#define SLSI_PSID_DOT11_TDLS_PEER_UAPSD_INDICATION_WINDOW 0x0035 - -/******************************************************************************* - * NAME : Dot11AssociationSaQueryMaximumTimeout - * PSID : 100 (0x0064) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 1000 - * DESCRIPTION : - * Timeout (in TUs) before giving up on a Peer that has not responded to a - * SA Query frame. - *******************************************************************************/ -#define SLSI_PSID_DOT11_ASSOCIATION_SA_QUERY_MAXIMUM_TIMEOUT 0x0064 - -/******************************************************************************* - * NAME : Dot11AssociationSaQueryRetryTimeout - * PSID : 101 (0x0065) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 201 - * DESCRIPTION : - * Timeout (in TUs) before trying a Query Request frame. - *******************************************************************************/ -#define SLSI_PSID_DOT11_ASSOCIATION_SA_QUERY_RETRY_TIMEOUT 0x0065 - -/******************************************************************************* - * NAME : Dot11RtsThreshold - * PSID : 121 (0x0079) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : octet - * MIN : 0 - * MAX : 65536 - * DEFAULT : 65536 - * DESCRIPTION : - * Size of an MPDU, below which an RTS/CTS handshake shall not be performed, - * except as RTS/CTS is used as a cross modulation protection mechanism as - * defined in 9.10. An RTS/CTS handshake shall be performed at the beginning - * of any frame exchange sequence where the MPDU is of type Data or - * Management, the MPDU has an individual address in the Address1 field, and - * the length of the MPDU is greater than this threshold. (For additional - * details, refer to Table 21 in 9.7.) Setting larger than the maximum MSDU - * size shall have the effect of turning off the RTS/CTS handshake for - * frames of Data or Management type transmitted by this STA. Setting to - * zero shall have the effect of turning on the RTS/CTS handshake for all - * frames of Data or Management type transmitted by this STA. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RTS_THRESHOLD 0x0079 - -/******************************************************************************* - * NAME : Dot11ShortRetryLimit - * PSID : 122 (0x007A) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 255 - * DEFAULT : 32 - * DESCRIPTION : - * Maximum number of transmission attempts of a frame, the length of which - * is less than or equal to dot11RTSThreshold, that shall be made before a - * failure condition is indicated. - *******************************************************************************/ -#define SLSI_PSID_DOT11_SHORT_RETRY_LIMIT 0x007A - -/******************************************************************************* - * NAME : Dot11LongRetryLimit - * PSID : 123 (0x007B) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 255 - * DEFAULT : 4 - * DESCRIPTION : - * Maximum number of transmission attempts of a frame, the length of which - * is greater than dot11RTSThreshold, that shall be made before a failure - * condition is indicated. - *******************************************************************************/ -#define SLSI_PSID_DOT11_LONG_RETRY_LIMIT 0x007B - -/******************************************************************************* - * NAME : Dot11FragmentationThreshold - * PSID : 124 (0x007C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 256 - * MAX : 11500 - * DEFAULT : 3000 - * DESCRIPTION : - * Current maximum size, in octets, of the MPDU that may be delivered to the - * security encapsulation. This maximum size does not apply when an MSDU is - * transmitted using an HT-immediate or HTdelayed Block Ack agreement, or - * when an MSDU or MMPDU is carried in an AMPDU that does not contain a VHT - * single MPDU. Fields added to the frame by security encapsulation are not - * counted against the limit specified. Except as described above, an MSDU - * or MMPDU is fragmented when the resulting frame has an individual address - * in the Address1 field, and the length of the frame is larger than this - * threshold, excluding security encapsulation fields. The default value is - * the lesser of 11500 or the aMPDUMaxLength or the aPSDUMaxLength of the - * attached PHY and the value never exceeds the lesser of 11500 or the - * aMPDUMaxLength or the aPSDUMaxLength of the attached PHY. - *******************************************************************************/ -#define SLSI_PSID_DOT11_FRAGMENTATION_THRESHOLD 0x007C - -/******************************************************************************* - * NAME : Dot11RtsSuccessCount - * PSID : 146 (0x0092) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * This counter shall increment when a CTS is received in response to an - * RTS. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RTS_SUCCESS_COUNT 0x0092 - -/******************************************************************************* - * NAME : Dot11AckFailureCount - * PSID : 148 (0x0094) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * This counter shall increment when an ACK is not received when expected. - *******************************************************************************/ -#define SLSI_PSID_DOT11_ACK_FAILURE_COUNT 0x0094 - -/******************************************************************************* - * NAME : Dot11MulticastReceivedFrameCount - * PSID : 150 (0x0096) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * This counter shall increment when a MSDU is received with the multicast - * bit set in the destination MAC address. - *******************************************************************************/ -#define SLSI_PSID_DOT11_MULTICAST_RECEIVED_FRAME_COUNT 0x0096 - -/******************************************************************************* - * NAME : Dot11FcsErrorCount - * PSID : 151 (0x0097) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : -9223372036854775808 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * This counter shall increment when an FCS error is detected in a received - * MPDU. - *******************************************************************************/ -#define SLSI_PSID_DOT11_FCS_ERROR_COUNT 0x0097 - -/******************************************************************************* - * NAME : Dot11WepUndecryptableCount - * PSID : 153 (0x0099) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * This counter shall increment when a frame is received with the WEP - * subfield of the Frame Control field set to one and the WEPOn value for - * the key mapped to the transmitter's MAC address indicates that the - * frame should not have been encrypted or that frame is discarded due to - * the receiving STA not implementing the privacy option. - *******************************************************************************/ -#define SLSI_PSID_DOT11_WEP_UNDECRYPTABLE_COUNT 0x0099 - -/******************************************************************************* - * NAME : Dot11ManufacturerProductVersion - * PSID : 183 (0x00B7) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 300 - * DEFAULT : - * DESCRIPTION : - * Printable string used to identify the manufacturer's product version - * of the resource. - *******************************************************************************/ -#define SLSI_PSID_DOT11_MANUFACTURER_PRODUCT_VERSION 0x00B7 - -/******************************************************************************* - * NAME : Dot11RsnaStatsStaAddress - * PSID : 430 (0x01AE) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The MAC address of the STA to which the statistics in this conceptual row - * belong. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_STA_ADDRESS 0x01AE - -/******************************************************************************* - * NAME : Dot11RsnaStatsTkipicvErrors - * PSID : 433 (0x01B1) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Counts the number of TKIP ICV errors encountered when decrypting packets - * for the STA. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_TKIPICV_ERRORS 0x01B1 - -/******************************************************************************* - * NAME : Dot11RsnaStatsTkipLocalMicFailures - * PSID : 434 (0x01B2) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Counts the number of MIC failures encountered when checking the integrity - * of packets received from the STA at this entity. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_TKIP_LOCAL_MIC_FAILURES 0x01B2 - -/******************************************************************************* - * NAME : Dot11RsnaStatsTkipRemoteMicFailures - * PSID : 435 (0x01B3) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Counts the number of MIC failures encountered by the STA identified by - * dot11RSNAStatsSTAAddress and reported back to this entity. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_TKIP_REMOTE_MIC_FAILURES 0x01B3 - -/******************************************************************************* - * NAME : Dot11RsnaStatsCcmpReplays - * PSID : 436 (0x01B4) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of received CCMP MPDUs discarded by the replay mechanism. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_CCMP_REPLAYS 0x01B4 - -/******************************************************************************* - * NAME : Dot11RsnaStatsCcmpDecryptErrors - * PSID : 437 (0x01B5) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of received MPDUs discarded by the CCMP decryption algorithm. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_CCMP_DECRYPT_ERRORS 0x01B5 - -/******************************************************************************* - * NAME : Dot11RsnaStatsTkipReplays - * PSID : 438 (0x01B6) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Counts the number of TKIP replay errors detected. - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_TKIP_REPLAYS 0x01B6 - -/******************************************************************************* - * NAME : Dot11RsnaStatsRobustMgmtCcmpReplays - * PSID : 441 (0x01B9) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of received Robust Management frame MPDUs discarded due to - * CCMP replay errors - *******************************************************************************/ -#define SLSI_PSID_DOT11_RSNA_STATS_ROBUST_MGMT_CCMP_REPLAYS 0x01B9 - -/******************************************************************************* - * NAME : UnifiMlmeConnectionTimeout - * PSID : 2000 (0x07D0) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_CONNECTION_TIMEOUT 0x07D0 - -/******************************************************************************* - * NAME : UnifiMlmeScanChannelMaxScanTime - * PSID : 2001 (0x07D1) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 14 - * MAX : 14 - * DEFAULT : { 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * Test only: overrides max_scan_time. 0 indicates not used. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_CHANNEL_MAX_SCAN_TIME 0x07D1 - -/******************************************************************************* - * NAME : UnifiMlmeScanChannelProbeInterval - * PSID : 2002 (0x07D2) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 14 - * MAX : 14 - * DEFAULT : { 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * Test only: overrides probe interval. 0 indicates not used. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_CHANNEL_PROBE_INTERVAL 0x07D2 - -/******************************************************************************* - * NAME : UnifiMlmeScanChannelRule - * PSID : 2003 (0x07D3) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 4 - * MAX : 4 - * DEFAULT : { 0X00, 0X01, 0X00, 0X01 } - * DESCRIPTION : - * Rules for channel scanners. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_CHANNEL_RULE 0x07D3 - -/******************************************************************************* - * NAME : UnifiMlmeDataReferenceTimeout - * PSID : 2005 (0x07D5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65534 - * DEFAULT : - * DESCRIPTION : - * Maximum time, in TU, allowed for the data in data references - * corresponding to MLME primitives to be made available to the firmware. - * The special value 0 specifies an infinite timeout. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_DATA_REFERENCE_TIMEOUT 0x07D5 - -/******************************************************************************* - * NAME : UnifiMlmeScanProbeInterval - * PSID : 2007 (0x07D7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_PROBE_INTERVAL 0x07D7 - -/******************************************************************************* - * NAME : UnifiMlmeScanHighRssiThreshold - * PSID : 2008 (0x07D8) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : -90 - * DESCRIPTION : - * Minimum RSSI, in dB, for a scan indication to be kept. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_HIGH_RSSI_THRESHOLD 0x07D8 - -/******************************************************************************* - * NAME : UnifiMlmeScanDeltaRssiThreshold - * PSID : 2010 (0x07DA) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 255 - * DEFAULT : 20 - * DESCRIPTION : - * Magnitude of the change in RSSI for which a scan result will be issued. - * In dB. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_DELTA_RSSI_THRESHOLD 0x07DA - -/******************************************************************************* - * NAME : UnifiMlmeScanMaximumAge - * PSID : 2014 (0x07DE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_MAXIMUM_AGE 0x07DE - -/******************************************************************************* - * NAME : UnifiMlmeScanMaximumResults - * PSID : 2015 (0x07DF) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 100 - * DESCRIPTION : - * Max number of scan results, per sps, which will be stored before the - * oldest result is discarded, irrespective of its age. The value 0 - * specifies no maximum. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_MAXIMUM_RESULTS 0x07DF - -/******************************************************************************* - * NAME : UnifiMlmeAutonomousScanNoisy - * PSID : 2016 (0x07E0) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_AUTONOMOUS_SCAN_NOISY 0x07E0 - -/******************************************************************************* - * NAME : UnifiChannelBusyThreshold - * PSID : 2018 (0x07E2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 100 - * DEFAULT : 25 - * DESCRIPTION : - * The threshold in percentage of CCA busy time when a channel would be - * considered busy - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CHANNEL_BUSY_THRESHOLD 0x07E2 - -/******************************************************************************* - * NAME : UnifiMacSequenceNumberRandomisationActivated - * PSID : 2020 (0x07E4) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enabling Sequence Number Randomisation to be applied for Probe Requests - * when scanning. Note: Randomisation only happens, if mac address gets - * randomised. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAC_SEQUENCE_NUMBER_RANDOMISATION_ACTIVATED 0x07E4 - -/******************************************************************************* - * NAME : UnifiFirmwareBuildId - * PSID : 2021 (0x07E5) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Numeric build identifier for this firmware build. This should normally be - * displayed in decimal. The textual build identifier is available via the - * standard dot11manufacturerProductVersion MIB attribute. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FIRMWARE_BUILD_ID 0x07E5 - -/******************************************************************************* - * NAME : UnifiChipVersion - * PSID : 2022 (0x07E6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Numeric identifier for the UniFi silicon revision (as returned by the - * GBL_CHIP_VERSION hardware register). Other than being different for each - * design variant (but not for alternative packaging options), the - * particular values returned do not have any significance. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CHIP_VERSION 0x07E6 - -/******************************************************************************* - * NAME : UnifiFirmwarePatchBuildId - * PSID : 2023 (0x07E7) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Numeric build identifier for the patch set that has been applied to this - * firmware image. This should normally be displayed in decimal. For a - * patched ROM build there will be two build identifiers, the first will - * correspond to the base ROM image, the second will correspond to the patch - * set that has been applied. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FIRMWARE_PATCH_BUILD_ID 0x07E7 - -/******************************************************************************* - * NAME : UnifiHtCapabilitiesSoftAp - * PSID : 2028 (0x07EC) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 21 - * MAX : 21 - * DEFAULT : { 0XEF, 0X0A, 0X17, 0XFF, 0XFF, 0X00, 0X00, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * HT capabilities of the chip. See SC-503520-SP for further details. NOTE: - * Greenfield has been disabled due to interoperability issues wuth SGI. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_HT_CAPABILITIES_SOFT_AP 0x07EC - -/******************************************************************************* - * NAME : UnifiSoftAp40MhzOn24g - * PSID : 2029 (0x07ED) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables 40MHz operation on 2.4GHz band for SoftAP. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SOFT_AP40_MHZ_ON24G 0x07ED - -/******************************************************************************* - * NAME : UnifiBasicCapabilities - * PSID : 2030 (0x07EE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X0730 - * DESCRIPTION : - * The 16-bit field follows the coding of IEEE 802.11 Capability - * Information. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BASIC_CAPABILITIES 0x07EE - -/******************************************************************************* - * NAME : UnifiExtendedCapabilities - * PSID : 2031 (0x07EF) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 9 - * MAX : 9 - * DEFAULT : { 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X40, 0X80 } - * DESCRIPTION : - * Extended capabilities. Bit field definition and coding follows IEEE - * 802.11 Extended Capability Information Element, with spare subfields for - * capabilities that are independent from chip/firmware implementation. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES 0x07EF - -/******************************************************************************* - * NAME : UnifiHtCapabilities - * PSID : 2032 (0x07F0) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 21 - * MAX : 21 - * DEFAULT : { 0XEF, 0X0A, 0X17, 0XFF, 0XFF, 0X00, 0X00, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * HT capabilities of the chip. See SC-503520-SP for further details. NOTE: - * Greenfield has been disabled due to interoperability issues wuth SGI. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_HT_CAPABILITIES 0x07F0 - -/******************************************************************************* - * NAME : UnifiRsnCapabilities - * PSID : 2034 (0x07F2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSN_CAPABILITIES 0x07F2 - -/******************************************************************************* - * NAME : Unifi24G40MhzChannels - * PSID : 2035 (0x07F3) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables 40Mz wide channels in the 2.4G band for STA. - *******************************************************************************/ -#define SLSI_PSID_UNIFI24_G40_MHZ_CHANNELS 0x07F3 - -/******************************************************************************* - * NAME : UnifiExtendedCapabilitiesDisabled - * PSID : 2036 (0x07F4) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Suppress - * extended capabilities IE being sent in the association request. Please - * note that this may fix IOP issues with Aruba APs in WMMAC. Singed Decimal - *******************************************************************************/ -#define SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES_DISABLED 0x07F4 - -/******************************************************************************* - * NAME : UnifiSupportedDataRates - * PSID : 2041 (0x07F9) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * UNITS : 500 kbps - * MIN : 2 - * MAX : 16 - * DEFAULT : { 0X02, 0X04, 0X0B, 0X0C, 0X12, 0X16, 0X18, 0X24, 0X30, 0X48, 0X60, 0X6C } - * DESCRIPTION : - * Defines the supported non-HT data rates. It is encoded as N+1 octets - * where the first octet is N and the subsequent octets each describe a - * single supported rate. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SUPPORTED_DATA_RATES 0x07F9 - -/******************************************************************************* - * NAME : UnifiRadioMeasurementActivated - * PSID : 2043 (0x07FB) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * When TRUE Radio Measurements are supported. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_MEASUREMENT_ACTIVATED 0x07FB - -/******************************************************************************* - * NAME : UnifiRadioMeasurementCapabilities - * PSID : 2044 (0x07FC) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 5 - * MAX : 5 - * DEFAULT : { 0X71, 0X00, 0X00, 0X00, 0X04 } - * DESCRIPTION : - * RM Enabled capabilities of the chip. See SC-503520-SP for further - * details. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_MEASUREMENT_CAPABILITIES 0x07FC - -/******************************************************************************* - * NAME : UnifiVhtActivated - * PSID : 2045 (0x07FD) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables VHT mode. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_VHT_ACTIVATED 0x07FD - -/******************************************************************************* - * NAME : UnifiHtActivated - * PSID : 2046 (0x07FE) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables HT mode. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_HT_ACTIVATED 0x07FE - -/******************************************************************************* - * NAME : UnifiEnableTwoSimultaneousPassiveScansSameBand - * PSID : 2047 (0x07FF) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enable two passive scans to be simultaneously scheduled on two distinct - * channels at the same. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ENABLE_TWO_SIMULTANEOUS_PASSIVE_SCANS_SAME_BAND 0x07FF - -/******************************************************************************* - * NAME : UnifiRoamingEnabled - * PSID : 2049 (0x0801) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enable Roaming functionality - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAMING_ENABLED 0x0801 - -/******************************************************************************* - * NAME : UnifiRssiRoamScanTrigger - * PSID : 2050 (0x0802) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : -75 - * DESCRIPTION : - * The RSSI value, in dBm, below which roaming scan shall start. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSI_ROAM_SCAN_TRIGGER 0x0802 - -/******************************************************************************* - * NAME : UnifiRoamDeltaTrigger - * PSID : 2051 (0x0803) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 255 - * DEFAULT : 10 - * DESCRIPTION : - * Hysteresis value, in dBm, for UnifiRssiRoamScanTrigger and - * unifiCURoamScanTrigger. i.e.: If the current AP RSSI is greater than - * UnifiRssiRoamScanTrigger+ UnifiRssiRoamDeltaTrigger, soft roaming scan - * can be terminated. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_DELTA_TRIGGER 0x0803 - -/******************************************************************************* - * NAME : UnifiRoamCachedChannelScanPeriod - * PSID : 2052 (0x0804) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 1 - * MAX : 4294967295 - * DEFAULT : 20000000 - * DESCRIPTION : - * The scan period for cached channels background roaming (microseconds) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_CACHED_CHANNEL_SCAN_PERIOD 0x0804 - -/******************************************************************************* - * NAME : UnifiFullRoamScanPeriod - * PSID : 2053 (0x0805) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 1 - * MAX : 4294967295 - * DEFAULT : 30000000 - * DESCRIPTION : - * NCHO: For certification and Host use only. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FULL_ROAM_SCAN_PERIOD 0x0805 - -/******************************************************************************* - * NAME : UnifiRoamSoftRoamingEnabled - * PSID : 2054 (0x0806) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables CASE_1 and CASE_2 scans. Host writes to the key, firmware reads - * it. See MFW-183 for details. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_SOFT_ROAMING_ENABLED 0x0806 - -/******************************************************************************* - * NAME : UnifiRoamScanBand - * PSID : 2055 (0x0807) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 2 - * DEFAULT : 2 - * DESCRIPTION : - * Indicates whether only intra-band or all-band should be used for roaming - * scan. 2 - Roaming across band 1 - Roaming within band - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_SCAN_BAND 0x0807 - -/******************************************************************************* - * NAME : UnifiRoamScanMaxActiveChannelTime - * PSID : 2057 (0x0809) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 65535 - * DEFAULT : 120 - * DESCRIPTION : - * NCHO: Name confusion for Host compatibility. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_SCAN_MAX_ACTIVE_CHANNEL_TIME 0x0809 - -/******************************************************************************* - * NAME : UnifiRoamFullChannelScanFrequency - * PSID : 2058 (0x080A) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 65535 - * DEFAULT : 9 - * DESCRIPTION : - * Every how many cached channel scans run a full channel scan. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_FULL_CHANNEL_SCAN_FREQUENCY 0x080A - -/******************************************************************************* - * NAME : UnifiRoamMode - * PSID : 2060 (0x080C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 2 - * DEFAULT : 1 - * DESCRIPTION : - * Enable/Disable host resume when roaming. 0: Wake up the host all the - * time. 1: Only wakeup the host if the AP is not white-listed. 2: Don't - * wake up the host. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_MODE 0x080C - -/******************************************************************************* - * NAME : UnifiRssiRoamScanNoCandidateDeltaTrigger - * PSID : 2064 (0x0810) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 255 - * DEFAULT : 10 - * DESCRIPTION : - * The value, in dBm, by which unifiRssiRoamScanTrigger is lowered when no - * roaming candidates are found. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSI_ROAM_SCAN_NO_CANDIDATE_DELTA_TRIGGER 0x0810 - -/******************************************************************************* - * NAME : UnifiRoamEapTimeout - * PSID : 2065 (0x0811) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 200 - * DESCRIPTION : - * Timeout, in ms, for receiving the first EAP/EAPOL frame from the AP - * during roaming - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_EAP_TIMEOUT 0x0811 - -/******************************************************************************* - * NAME : UnifiRoamScanControl - * PSID : 2067 (0x0813) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * NCHO: Enable MCD NCHO feature. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_SCAN_CONTROL 0x0813 - -/******************************************************************************* - * NAME : UnifiRoamDfsScanMode - * PSID : 2068 (0x0814) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 2 - * DEFAULT : 1 - * DESCRIPTION : - * NCHO: For certification and Host use only. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_DFS_SCAN_MODE 0x0814 - -/******************************************************************************* - * NAME : UnifiRoamScanHomeTime - * PSID : 2069 (0x0815) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 40 - * MAX : 65535 - * DEFAULT : 45 - * DESCRIPTION : - * NCHO: The time, in TU, to spend NOT scanning during a HomeAway scan. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_SCAN_HOME_TIME 0x0815 - -/******************************************************************************* - * NAME : UnifiRoamScanHomeAwayTime - * PSID : 2070 (0x0816) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 40 - * MAX : 65535 - * DEFAULT : 100 - * DESCRIPTION : - * NCHO: The time, in TU, to spend scanning during a HomeAway scan. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_SCAN_HOME_AWAY_TIME 0x0816 - -/******************************************************************************* - * NAME : UnifiRoamScanNProbe - * PSID : 2072 (0x0818) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2 - * DESCRIPTION : - * NCHO: The number of ProbeRequest frames per channel. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_SCAN_NPROBE 0x0818 - -/******************************************************************************* - * NAME : UnifiApOlbcDuration - * PSID : 2076 (0x081C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 300 - * DESCRIPTION : - * How long, in milliseconds, the AP enables reception of BEACON frames to - * perform Overlapping Legacy BSS Condition(OLBC). If set to 0 then OLBC is - * disabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_OLBC_DURATION 0x081C - -/******************************************************************************* - * NAME : UnifiApOlbcInterval - * PSID : 2077 (0x081D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2000 - * DESCRIPTION : - * How long, in milliseconds, between periods of receiving BEACON frames to - * perform Overlapping Legacy BSS Condition(OLBC). This value MUST exceed - * the OBLC duration MIB unifiApOlbcDuration. If set to 0 then OLBC is - * disabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_OLBC_INTERVAL 0x081D - -/******************************************************************************* - * NAME : UnifiMlmednsSupportEnabled - * PSID : 2078 (0x081E) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * This MIB enables support for transmitting DNS frame via MLME. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLMEDNS_SUPPORT_ENABLED 0x081E - -/******************************************************************************* - * NAME : UnifiOffchannelScheduleTimeout - * PSID : 2079 (0x081F) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1000 - * DESCRIPTION : - * Maximum timeout in ms the Offchannel FSM will wait until the complete - * dwell time is scheduled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OFFCHANNEL_SCHEDULE_TIMEOUT 0x081F - -/******************************************************************************* - * NAME : UnifiFrameResponseTimeout - * PSID : 2080 (0x0820) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 500 - * DEFAULT : 200 - * DESCRIPTION : - * Timeout, in TU, to wait for a frame(Auth, Assoc, ReAssoc) after Rame - * replies to a send frame request - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FRAME_RESPONSE_TIMEOUT 0x0820 - -/******************************************************************************* - * NAME : UnifiConnectionFailureTimeout - * PSID : 2081 (0x0821) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 20000 - * DEFAULT : 10000 - * DESCRIPTION : - * Timeout, in TU, for a frame retry before giving up. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CONNECTION_FAILURE_TIMEOUT 0x0821 - -/******************************************************************************* - * NAME : UnifiConnectingProbeTimeout - * PSID : 2082 (0x0822) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 10 - * DESCRIPTION : - * How long, in TU, to wait for a ProbeRsp when syncronising before - * resending a ProbeReq - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CONNECTING_PROBE_TIMEOUT 0x0822 - -/******************************************************************************* - * NAME : UnifiDisconnectTimeout - * PSID : 2083 (0x0823) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 3000 - * DEFAULT : 1500 - * DESCRIPTION : - * Timeout, in milliseconds, to perform a disconnect or disconnect all STAs - * (triggered by MLME_DISCONNECT-REQ or MLME_DISCONNECT-REQ - * 00:00:00:00:00:00) before responding with MLME-DISCONNECT-IND and - * aborting the disconnection attempt. This is particulary important when a - * SoftAP is attempting to disconnect associated stations which might have - * "silently" left the ESS. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DISCONNECT_TIMEOUT 0x0823 - -/******************************************************************************* - * NAME : UnifiFrameResponseCfmTxLifetimeTimeout - * PSID : 2084 (0x0824) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Timeout, in TU, to wait to retry a frame (Auth, Assoc, ReAssoc) after TX - * Cfm trasnmission_status = TxLifetime. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FRAME_RESPONSE_CFM_TX_LIFETIME_TIMEOUT 0x0824 - -/******************************************************************************* - * NAME : UnifiFrameResponseCfmFailureTimeout - * PSID : 2085 (0x0825) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 40 - * DESCRIPTION : - * Timeout, in TU, to wait to retry a frame (Auth, Assoc, ReAssoc) after TX - * Cfm trasnmission_status != Successful | TxLifetime. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FRAME_RESPONSE_CFM_FAILURE_TIMEOUT 0x0825 - -/******************************************************************************* - * NAME : UnifiForceActiveDuration - * PSID : 2086 (0x0826) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 1000 - * DEFAULT : 200 - * DESCRIPTION : - * How long, in milliseconds, the firmware temporarily extends PowerSave for - * STA as a workaround for wonky APs such as D-link. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FORCE_ACTIVE_DURATION 0x0826 - -/******************************************************************************* - * NAME : UnifiMlmeScanMaxNumberOfProbeSets - * PSID : 2087 (0x0827) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_MAX_NUMBER_OF_PROBE_SETS 0x0827 - -/******************************************************************************* - * NAME : UnifiMlmeScanStopIfLessThanXFrames - * PSID : 2088 (0x0828) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 4 - * DESCRIPTION : - * Stop scanning on a channel if less than X Beacons or Probe Responses are - * received. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_STOP_IF_LESS_THAN_XFRAMES 0x0828 - -/******************************************************************************* - * NAME : UnifiApAssociationTimeout - * PSID : 2089 (0x0829) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2000 - * DESCRIPTION : - * SoftAP: Permitted time for a station to complete associatation with FW - * acting as AP in milliseconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_ASSOCIATION_TIMEOUT 0x0829 - -/******************************************************************************* - * NAME : UnifiHostNumAntennaControlActivated - * PSID : 2091 (0x082B) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Host has a control of number of antenna to use - *******************************************************************************/ -#define SLSI_PSID_UNIFI_HOST_NUM_ANTENNA_CONTROL_ACTIVATED 0x082B - -/******************************************************************************* - * NAME : UnifiPeerBandwidth - * PSID : 2094 (0x082E) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The bandwidth used with peer station prior it disconnects - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PEER_BANDWIDTH 0x082E - -/******************************************************************************* - * NAME : UnifiCurrentPeerNss - * PSID : 2095 (0x082F) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The number of spatial streams used with peer station prior it disconnects - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CURRENT_PEER_NSS 0x082F - -/******************************************************************************* - * NAME : UnifiPeerTxDataRate - * PSID : 2096 (0x0830) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The tx rate that was used for transmissions prior disconnection - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PEER_TX_DATA_RATE 0x0830 - -/******************************************************************************* - * NAME : UnifiPeerRssi - * PSID : 2097 (0x0831) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * The recorded RSSI from peer station prior it disconnects - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PEER_RSSI 0x0831 - -/******************************************************************************* - * NAME : UnifiMlmeStationInactivityTimeout - * PSID : 2098 (0x0832) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 3 - * DESCRIPTION : - * Timeout, in seconds, for instigating ConnectonFailure procedures. Setting - * it to less than 3 seconds may result in frequent disconnection or roaming - * with the AP. Disable with Zero. Values lower than - * INACTIVITY_MINIMUM_TIMEOUT becomes INACTIVITY_MINIMUM_TIMEOUT. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_STATION_INACTIVITY_TIMEOUT 0x0832 - -/******************************************************************************* - * NAME : UnifiMlmeCliInactivityTimeout - * PSID : 2099 (0x0833) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Timeout, in seconds, for instigating ConnectonFailure procedures. Zero - * value disables the feature. Any value written lower than - * INACTIVITY_MINIMUM_TIMEOUT becomes INACTIVITY_MINIMUM_TIMEOUT. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_CLI_INACTIVITY_TIMEOUT 0x0833 - -/******************************************************************************* - * NAME : UnifiMlmeStationInitialKickTimeout - * PSID : 2100 (0x0834) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 50 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Timeout, in - * milliseconds, for sending the AP a NULL frame to kick off the EAPOL - * exchange. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_STATION_INITIAL_KICK_TIMEOUT 0x0834 - -/******************************************************************************* - * NAME : UnifiUartConfigure - * PSID : 2110 (0x083E) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * UART configuration using the values of the other unifiUart* attributes. - * The value supplied for this attribute is ignored. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_UART_CONFIGURE 0x083E - -/******************************************************************************* - * NAME : UnifiUartPios - * PSID : 2111 (0x083F) - * PER INTERFACE?: NO - * TYPE : unifiUartPios - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Specification of which PIOs should be connected to the UART. Currently - * defined values are: 1 - UART not used; all PIOs are available for other - * uses. 2 - Data transmit and receive connected to PIO[12] and PIO[14] - * respectively. No hardware handshaking lines. 3 - Data and handshaking - * lines connected to PIO[12:15]. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_UART_PIOS 0x083F - -/******************************************************************************* - * NAME : UnifiClockFrequency - * PSID : 2140 (0x085C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : kHz - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Query the nominal frequency of the external clock source or crystal - * oscillator used by UniFi. The clock frequency is a system parameter and - * can not be modified by key. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CLOCK_FREQUENCY 0x085C - -/******************************************************************************* - * NAME : UnifiCrystalFrequencyTrim - * PSID : 2141 (0x085D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 63 - * DEFAULT : 31 - * DESCRIPTION : - * The IEEE 802.11 standard requires a frequency accuracy of either +/- 20 - * ppm or +/- 25 ppm depending on the physical layer being used. If - * UniFi's frequency reference is a crystal then this attribute should - * be used to tweak the oscillating frequency to compensate for design- or - * device-specific variations. Each step change trims the frequency by - * approximately 2 ppm. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CRYSTAL_FREQUENCY_TRIM 0x085D - -/******************************************************************************* - * NAME : UnifiEnableDorm - * PSID : 2142 (0x085E) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Enable Dorm - * (deep sleep). When disabled, WLAN will not switch the radio power domain - * on/off *and* it will always veto deep sleep. Setting the value to TRUE - * means dorm functionality will behave normally. The intention is *not* for - * this value to be changed at runtime. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ENABLE_DORM 0x085E - -/******************************************************************************* - * NAME : UnifiExternalClockDetect - * PSID : 2146 (0x0862) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * If UniFi is running with an external fast clock source, i.e. - * unifiExternalFastClockRequest is set, it is common for this clock to be - * shared with other devices. Setting to true causes UniFi to detect when - * the clock is present (presumably in response to a request from another - * device), and to perform any pending activities at that time rather than - * requesting the clock again some time later. This is likely to reduce - * overall system power consumption by reducing the total time that the - * clock needs to be active. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_EXTERNAL_CLOCK_DETECT 0x0862 - -/******************************************************************************* - * NAME : UnifiExternalFastClockRequest - * PSID : 2149 (0x0865) - * PER INTERFACE?: NO - * TYPE : unifiExternalFastClockRequest - * MIN : 0 - * MAX : 255 - * DEFAULT : 1 - * DESCRIPTION : - * It is possible to supply UniFi with an external fast reference clock, as - * an alternative to using a crystal. If such a clock is used then it is - * only required when UniFi is active. A signal can be output on PIO[2] or - * if the version of UniFi in use is the UF602x or later, any PIO may be - * used (see unifiExternalFastClockRequestPIO) to indicate when UniFi - * requires a fast clock. Setting makes this signal become active and - * determines the type of signal output. 0 - No clock request. 1 - Non - * inverted, totem pole. 2 - Inverted, totem pole. 3 - Open drain. 4 - Open - * source. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_EXTERNAL_FAST_CLOCK_REQUEST 0x0865 - -/******************************************************************************* - * NAME : UnifiWatchdogTimeout - * PSID : 2152 (0x0868) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : ms - * MIN : 1 - * MAX : 65535 - * DEFAULT : 1500 - * DESCRIPTION : - * Maximum time the background may be busy or locked out for. If this time - * is exceeded, UniFi will reset. If this key is set to 65535 then the - * watchdog will be disabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_WATCHDOG_TIMEOUT 0x0868 - -/******************************************************************************* - * NAME : UnifiScanParameters - * PSID : 2154 (0x086A) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 18 - * MAX : 18 - * DEFAULT : - * DESCRIPTION : - * Scan parameters. Each row of the table contains 2 entries for a scan: - * first entry when there is 0 registered VIFs, second - when there is 1 or - * more registered VIFs. Entry has the following structure: octet 0 - Scan - * priority (uint8) octet 1 - Scan Flags (uint8) (see unifiScanFlags) bit 0 - * - Enable Early Channel Exit (bool) bit 1 - Disable Scan (bool) bit 2 - - * Enable NCHO (bool) bit 3 - Enable MAC Randomization (bool) octet 2 ~ 3 - - * Probe Interval in Time Units (uint16) octet 4 ~ 5 - Max Active Channel - * Time in Time Units (uint16) octet 6 ~ 7 - Max Passive Channel Time in - * Time Units (uint16) octet 8 - Scan Policy (uint8) Size of each entry is 9 - * octets, row size is 18 octets. A Time Units value specifies a time - * interval as a multiple of TU (1024 us). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SCAN_PARAMETERS 0x086A - -/******************************************************************************* - * NAME : UnifiOverrideEdcaParamActivated - * PSID : 2155 (0x086B) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * To enable / disable, override STA edca config parameters with - * unifiOverrideEDCAParam. default: True - for volcano, and False - for - * others - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_EDCA_PARAM_ACTIVATED 0x086B - -/******************************************************************************* - * NAME : UnifiOverrideEdcaParam - * PSID : 2156 (0x086C) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * EDCA Parameters to be used if unifiOverrideEDCAParamEnable is true, - * indexed by unifiAccessClassIndex octet 0 - AIFSN octet 1 - [7:4] ECW MAX - * [3:0] ECW MIN octet 2 ~ 3 - TXOP[7:0] TXOP[15:8] in 32 usec units for - * both non-HT and HT connections. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_EDCA_PARAM 0x086C - -/******************************************************************************* - * NAME : UnifiExternalFastClockRequestPio - * PSID : 2158 (0x086E) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 15 - * DEFAULT : 9 - * DESCRIPTION : - * If an external fast reference clock is being supplied to UniFi as an - * alternative to a crystal (see unifiExternalFastClockRequest) and the - * version of UniFi in use is the UF602x or later, any PIO may be used as - * the external fast clock request output from UniFi. key determines the PIO - * to use. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_EXTERNAL_FAST_CLOCK_REQUEST_PIO 0x086E - -/******************************************************************************* - * NAME : UnifiRxDataRate - * PSID : 2196 (0x0894) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The bit rate of the last received frame on this VIF. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_DATA_RATE 0x0894 - -/******************************************************************************* - * NAME : UnifiPeerRxRetryCount - * PSID : 2198 (0x0896) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The number of retry packets from peer station - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PEER_RX_RETRY_COUNT 0x0896 - -/******************************************************************************* - * NAME : UnifiPeerRxMulticastCount - * PSID : 2199 (0x0897) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The number of multicast and broadcast packets received from peer station - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PEER_RX_MULTICAST_COUNT 0x0897 - -/******************************************************************************* - * NAME : UnifiRssi - * PSID : 2200 (0x0898) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dBm - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Running average of the Received Signal Strength Indication (RSSI) for - * packets received by UniFi's radio. The value should only be treated - * as an indication of the signal strength; it is not an accurate - * measurement. The result is only meaningful if the unifiRxExternalGain - * attribute is set to the correct calibration value. If UniFi is part of a - * BSS, only frames originating from devices in the BSS are reported (so far - * as this can be determined). The average is reset when UniFi joins or - * starts a BSS or is reset. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSI 0x0898 - -/******************************************************************************* - * NAME : UnifiLastBssRssi - * PSID : 2201 (0x0899) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Last BSS RSSI. See unifiRSSI description. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAST_BSS_RSSI 0x0899 - -/******************************************************************************* - * NAME : UnifiSnr - * PSID : 2202 (0x089A) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Provides a running average of the Signal to Noise Ratio (dB) for packets - * received by UniFi's radio. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SNR 0x089A - -/******************************************************************************* - * NAME : UnifiLastBssSnr - * PSID : 2203 (0x089B) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Last BSS SNR. See unifiSNR description. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAST_BSS_SNR 0x089B - -/******************************************************************************* - * NAME : UnifiSwTxTimeout - * PSID : 2204 (0x089C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : second - * MIN : 0 - * MAX : 65535 - * DEFAULT : 5 - * DESCRIPTION : - * Maximum time in seconds for a frame to be queued in firmware, ready to be - * sent, but not yet actually pumped to hardware. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SW_TX_TIMEOUT 0x089C - -/******************************************************************************* - * NAME : UnifiHwTxTimeout - * PSID : 2205 (0x089D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : milliseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : 512 - * DESCRIPTION : - * Maximum time in milliseconds for a frame to be queued in the - * hardware/DPIF. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_HW_TX_TIMEOUT 0x089D - -/******************************************************************************* - * NAME : UnifiRateStatsRxSuccessCount - * PSID : 2206 (0x089E) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of successful receptions of complete management and data - * frames at the rate indexed by unifiRateStatsIndex.This number will wrap - * to zero after the range is exceeded. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RATE_STATS_RX_SUCCESS_COUNT 0x089E - -/******************************************************************************* - * NAME : UnifiRateStatsTxSuccessCount - * PSID : 2207 (0x089F) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of successful (acknowledged) unicast transmissions of complete - * data or management frames the rate indexed by unifiRateStatsIndex. This - * number will wrap to zero after the range is exceeded. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RATE_STATS_TX_SUCCESS_COUNT 0x089F - -/******************************************************************************* - * NAME : UnifiTxDataRate - * PSID : 2208 (0x08A0) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The bit rate currently in use for transmissions of unicast data frames; - * On an infrastructure BSS, this is the data rate used in communicating - * with the associated access point, if there is none, an error is returned - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_DATA_RATE 0x08A0 - -/******************************************************************************* - * NAME : UnifiSnrExtraOffsetCck - * PSID : 2209 (0x08A1) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dB - * MIN : -32768 - * MAX : 32767 - * DEFAULT : 8 - * DESCRIPTION : - * This offset is added to SNR values received at 802.11b data rates. This - * accounts for differences in the RF pathway between 802.11b and 802.11g - * demodulators. The offset applies to values of unifiSNR as well as SNR - * values in scan indications. Not used in 5GHz mode. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SNR_EXTRA_OFFSET_CCK 0x08A1 - -/******************************************************************************* - * NAME : UnifiRssiMaxAveragingPeriod - * PSID : 2210 (0x08A2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : TU - * MIN : 1 - * MAX : 65535 - * DEFAULT : 3000 - * DESCRIPTION : - * Limits the period over which the value of unifiRSSI is averaged. If no - * more than unifiRSSIMinReceivedFrames frames have been received in the - * period, then the value of unifiRSSI is reset to the value of the next - * measurement and the rolling average is restarted. This ensures that the - * value is timely (although possibly poorly averaged) when little data is - * being received. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSI_MAX_AVERAGING_PERIOD 0x08A2 - -/******************************************************************************* - * NAME : UnifiRssiMinReceivedFrames - * PSID : 2211 (0x08A3) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 65535 - * DEFAULT : 2 - * DESCRIPTION : - * See the description of unifiRSSIMaxAveragingPeriod for how the - * combination of attributes is used. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSI_MIN_RECEIVED_FRAMES 0x08A3 - -/******************************************************************************* - * NAME : UnifiRateStatsRate - * PSID : 2212 (0x08A4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : 500 kbps - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The rate corresponding to the current table entry. The value is rounded - * to the nearest number of units where necessary. Most rates do not require - * rounding, but when short guard interval is in effect the rates are no - * longer multiples of the base unit. Note that there may be two occurrences - * of the value 130: the first corresponds to MCS index 7, and the second, - * if present, to MCS index 6 with short guard interval. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RATE_STATS_RATE 0x08A4 - -/******************************************************************************* - * NAME : UnifiLastBssTxDataRate - * PSID : 2213 (0x08A5) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Last BSS Tx DataRate. See unifiTxDataRate description. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAST_BSS_TX_DATA_RATE 0x08A5 - -/******************************************************************************* - * NAME : UnifiDiscardedFrameCount - * PSID : 2214 (0x08A6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * This is a counter that indicates the number of data and management frames - * that have been processed by the UniFi hardware but were discarded before - * being processed by the firmware. It does not include frames not processed - * by the hardware because they were not addressed to the local device, nor - * does it include frames discarded by the firmware in the course of normal - * MAC processing (which include, for example, frames in an appropriate - * encryption state and multicast frames not requested by the host). - * Typically this counter indicates lost data frames for which there was no - * buffer space; however, other cases may cause the counter to increment, - * such as receiving a retransmitted frame that was already successfully - * processed. Hence this counter should not be treated as a reliable guide - * to lost frames. The counter wraps to 0 after 65535. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DISCARDED_FRAME_COUNT 0x08A6 - -/******************************************************************************* - * NAME : UnifiMacrameDebugStats - * PSID : 2215 (0x08A7) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * MACRAME debug stats readout key. Use set to write a debug readout, then - * read the same key to get the actual readout. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MACRAME_DEBUG_STATS 0x08A7 - -/******************************************************************************* - * NAME : UnifiCurrentTsfTime - * PSID : 2218 (0x08AA) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : -9223372036854775808 - * MAX : 9223372036854775807 - * DEFAULT : - * DESCRIPTION : - * Get TSF time (last 32 bits) for the specified VIF. VIF index can't be 0 - * as that is treated as global VIF For station VIF - Correct BSS TSF wil - * only be reported after MLME-CONNECT.indication(success) indication to - * host. Note that if MAC Hardware is switched off then TSF returned is - * estimated value - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CURRENT_TSF_TIME 0x08AA - -/******************************************************************************* - * NAME : UnifiBaRxEnableTid - * PSID : 2219 (0x08AB) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X1555 - * DESCRIPTION : - * Configure Block Ack RX on a per-TID basis. Bit mask is two bits per TID - * (B1 = Not Used, B0 = enable). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BA_RX_ENABLE_TID 0x08AB - -/******************************************************************************* - * NAME : UnifiBaTxEnableTid - * PSID : 2221 (0x08AD) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X0557 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Configure - * Block Ack TX on a per-TID basis. Bit mask is two bits per TID (B1 = - * autosetup, B0 = enable). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BA_TX_ENABLE_TID 0x08AD - -/******************************************************************************* - * NAME : UnifiTrafficThresholdToSetupBa - * PSID : 2222 (0x08AE) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 100 - * DESCRIPTION : - * Sets the default Threshold (as packet count) to setup BA agreement per - * TID. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TRAFFIC_THRESHOLD_TO_SETUP_BA 0x08AE - -/******************************************************************************* - * NAME : UnifiDplaneTxAmsduHwCapability - * PSID : 2223 (0x08AF) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Returns 0 if A-MSDU size limited to 4K. Returns 1 is A-MSDU size is - * limited to 8K. This value is chip specific and limited by HW. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPLANE_TX_AMSDU_HW_CAPABILITY 0x08AF - -/******************************************************************************* - * NAME : UnifiDplaneTxAmsduSubframeCountMax - * PSID : 2224 (0x08B0) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 4 - * DEFAULT : 3 - * DESCRIPTION : - * Defines the maximum number of A-MSDU sub-frames per A-MSDU. A value of 1 - * indicates A-MSDU aggregation has been disabled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPLANE_TX_AMSDU_SUBFRAME_COUNT_MAX 0x08B0 - -/******************************************************************************* - * NAME : UnifiBaConfig - * PSID : 2225 (0x08B1) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X3FFF01 - * DESCRIPTION : - * Block Ack Configuration. It is composed of A-MSDU supported, TX MPDU per - * A-MPDU, RX Buffer size, TX Buffer size and Block Ack Timeout. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BA_CONFIG 0x08B1 - -/******************************************************************************* - * NAME : UnifiBaTxMaxNumber - * PSID : 2226 (0x08B2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X10 - * DESCRIPTION : - * Block Ack Configuration. Maximum number of BAs. Limited by HW. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BA_TX_MAX_NUMBER 0x08B2 - -/******************************************************************************* - * NAME : UnifiMoveBKtoBe - * PSID : 2227 (0x08B3) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : - * DESCRIPTION : - * Deprecated. Golden Certification MIB don't delete, change PSID or name - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MOVE_BKTO_BE 0x08B3 - -/******************************************************************************* - * NAME : UnifiBeaconReceived - * PSID : 2228 (0x08B4) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Access point beacon received count from connected AP - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BEACON_RECEIVED 0x08B4 - -/******************************************************************************* - * NAME : UnifiAcRetries - * PSID : 2229 (0x08B5) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * It represents the number of retransmitted frames under each ac priority - * (indexed by unifiAccessClassIndex). This number will wrap to zero after - * the range is exceeded. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AC_RETRIES 0x08B5 - -/******************************************************************************* - * NAME : UnifiRadioOnTime - * PSID : 2230 (0x08B6) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * msecs the radio is awake (32 bits number accruing over time). On - * multi-radio platforms an index to the radio instance is required - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_ON_TIME 0x08B6 - -/******************************************************************************* - * NAME : UnifiRadioTxTime - * PSID : 2231 (0x08B7) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * msecs the radio is transmitting (32 bits number accruing over time). On - * multi-radio platforms an index to the radio instance is required - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_TX_TIME 0x08B7 - -/******************************************************************************* - * NAME : UnifiRadioRxTime - * PSID : 2232 (0x08B8) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * msecs the radio is in active receive (32 bits number accruing over time). - * On multi-radio platforms an index to the radio instance is required - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_RX_TIME 0x08B8 - -/******************************************************************************* - * NAME : UnifiRadioScanTime - * PSID : 2233 (0x08B9) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * msecs the radio is awake due to all scan (32 bits number accruing over - * time). On multi-radio platforms an index to the radio instance is - * required - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_SCAN_TIME 0x08B9 - -/******************************************************************************* - * NAME : UnifiPsLeakyAp - * PSID : 2234 (0x08BA) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * indicate that this AP typically leaks packets beyond the guard time - * (5msecs). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PS_LEAKY_AP 0x08BA - -/******************************************************************************* - * NAME : UnifiTqamActivated - * PSID : 2235 (0x08BB) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables Vendor VHT IE for 256-QAM mode on 2.4GHz. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TQAM_ACTIVATED 0x08BB - -/******************************************************************************* - * NAME : UnifiRadioOnTimeNan - * PSID : 2236 (0x08BC) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * msecs the radio is awake due to NAN operations (32 bits number accruing - * over time). On multi-radio platforms an index to the radio instance is - * required - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_ON_TIME_NAN 0x08BC - -/******************************************************************************* - * NAME : UnifiOutputRadioInfoToKernelLog - * PSID : 2239 (0x08BF) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Print messages about the radio status to the Android Kernel Log. See - * document SC-508266-TC. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OUTPUT_RADIO_INFO_TO_KERNEL_LOG 0x08BF - -/******************************************************************************* - * NAME : UnifiNoAckActivationCount - * PSID : 2240 (0x08C0) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of frames that are discarded due to HW No-ack activated during - * test. This number will wrap to zero after the range is exceeded. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NO_ACK_ACTIVATION_COUNT 0x08C0 - -/******************************************************************************* - * NAME : UnifiRxFcsErrorCount - * PSID : 2241 (0x08C1) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of received frames that are discarded due to bad FCS (CRC). - * This number will wrap to zero after the range is exceeded. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_FCS_ERROR_COUNT 0x08C1 - -/******************************************************************************* - * NAME : UnifiBeaconsReceivedPercentage - * PSID : 2245 (0x08C5) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Percentage of beacons received, calculated as received / expected. The - * percentage is scaled to an integer value between 0 (0%) and 1000 (100%). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BEACONS_RECEIVED_PERCENTAGE 0x08C5 - -/******************************************************************************* - * NAME : UnifiArpDetectActivated - * PSID : 2246 (0x08C6) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enable feature support for Enhanced ARP Detect. This is required by - * Volcano. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ARP_DETECT_ACTIVATED 0x08C6 - -/******************************************************************************* - * NAME : UnifiArpDetectResponseCounter - * PSID : 2247 (0x08C7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Counter used to track ARP Response frame for Enhanced ARP Detect. This is - * required by Volcano. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ARP_DETECT_RESPONSE_COUNTER 0x08C7 - -/******************************************************************************* - * NAME : UnifiEnableMgmtTxPacketStats - * PSID : 2249 (0x08C9) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Consider management packets for TX stats counters - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ENABLE_MGMT_TX_PACKET_STATS 0x08C9 - -/******************************************************************************* - * NAME : UnifiSwToHwQueueStats - * PSID : 2250 (0x08CA) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The timing statistics of packets being queued between SW-HW - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SW_TO_HW_QUEUE_STATS 0x08CA - -/******************************************************************************* - * NAME : UnifiHostToSwQueueStats - * PSID : 2251 (0x08CB) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The timing statistics of packets being queued between HOST-SW - *******************************************************************************/ -#define SLSI_PSID_UNIFI_HOST_TO_SW_QUEUE_STATS 0x08CB - -/******************************************************************************* - * NAME : UnifiQueueStatsEnable - * PSID : 2252 (0x08CC) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables recording timing statistics of packets being queued between - * HOST-SW-HW - *******************************************************************************/ -#define SLSI_PSID_UNIFI_QUEUE_STATS_ENABLE 0x08CC - -/******************************************************************************* - * NAME : UnifiTxDataConfirm - * PSID : 2253 (0x08CD) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Allows to request on a per access class basis that an MA_UNITDATA.confirm - * be generated after each packet transfer. The default value is applied for - * all ACs. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_DATA_CONFIRM 0x08CD - -/******************************************************************************* - * NAME : UnifiThroughputDebug - * PSID : 2254 (0x08CE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * is used to access throughput related counters that can help diagnose - * throughput problems. The index of the MIB will access different counters, - * as described in SC-506328-DD. Setting any index for a VIF to any value, - * clears all DPLP debug stats for the MAC instance used by the VIF. This is - * useful mainly for debugging LAA or small scale throughput issues that - * require short term collection of the statistics. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_THROUGHPUT_DEBUG 0x08CE - -/******************************************************************************* - * NAME : UnifiLoadDpdLut - * PSID : 2255 (0x08CF) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 147 - * MAX : 147 - * DEFAULT : - * DESCRIPTION : - * Write a static DPD LUT to the FW, read DPD LUT from hardware - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LOAD_DPD_LUT 0x08CF - -/******************************************************************************* - * NAME : UnifiDpdMasterSwitch - * PSID : 2256 (0x08D0) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Enables Digital Pre-Distortion - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPD_MASTER_SWITCH 0x08D0 - -/******************************************************************************* - * NAME : UnifiDpdPredistortGains - * PSID : 2257 (0x08D1) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 14 - * MAX : 14 - * DEFAULT : - * DESCRIPTION : - * DPD pre-distort gains. Takes a range of frequencies, where f_min <= - * f_channel < f_max. The format is [freq_min_msb, freq_min_lsb, - * freq_max_msb, freq_max_lsb, DPD policy bitmap, bandwidth_bitmap, - * power_trim_enable, OFDM0_gain, OFDM1_gain, CCK_gain, TR_gain, CCK PSAT - * gain, OFDM PSAT gain]. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPD_PREDISTORT_GAINS 0x08D1 - -/******************************************************************************* - * NAME : UnifiOverrideDpdLut - * PSID : 2258 (0x08D2) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 147 - * MAX : 147 - * DEFAULT : - * DESCRIPTION : - * Write a DPD LUT directly to the HW - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_DPD_LUT 0x08D2 - -/******************************************************************************* - * NAME : UnifiGoogleMaxNumberOfPeriodicScans - * PSID : 2260 (0x08D4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_GOOGLE_MAX_NUMBER_OF_PERIODIC_SCANS 0x08D4 - -/******************************************************************************* - * NAME : UnifiGoogleMaxRssiSampleSize - * PSID : 2261 (0x08D5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_GOOGLE_MAX_RSSI_SAMPLE_SIZE 0x08D5 - -/******************************************************************************* - * NAME : UnifiGoogleMaxHotlistAPs - * PSID : 2262 (0x08D6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_GOOGLE_MAX_HOTLIST_APS 0x08D6 - -/******************************************************************************* - * NAME : UnifiGoogleMaxSignificantWifiChangeAPs - * PSID : 2263 (0x08D7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_GOOGLE_MAX_SIGNIFICANT_WIFI_CHANGE_APS 0x08D7 - -/******************************************************************************* - * NAME : UnifiGoogleMaxBssidHistoryEntries - * PSID : 2264 (0x08D8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_GOOGLE_MAX_BSSID_HISTORY_ENTRIES 0x08D8 - -/******************************************************************************* - * NAME : UnifiMacBeaconTimeout - * PSID : 2270 (0x08DE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : 128 - * DESCRIPTION : - * The maximum time in microseconds we want to stall TX data when expecting - * a beacon at EBRT time as a station. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAC_BEACON_TIMEOUT 0x08DE - -/******************************************************************************* - * NAME : UnifiStaUsesOneAntennaWhenIdle - * PSID : 2274 (0x08E2) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Allow the platform to downgrade antenna usage for STA VIFs to 1 if the - * VIF is idle. Only valid for multi-radio platforms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STA_USES_ONE_ANTENNA_WHEN_IDLE 0x08E2 - -/******************************************************************************* - * NAME : UnifiStaUsesMultiAntennasDuringConnect - * PSID : 2275 (0x08E3) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Allow the platform to use multiple antennas for STA VIFs during the - * connect phase. Only valid for multi-radio platforms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STA_USES_MULTI_ANTENNAS_DURING_CONNECT 0x08E3 - -/******************************************************************************* - * NAME : UnifiApUsesOneAntennaWhenPeersIdle - * PSID : 2276 (0x08E4) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Allow the platform to downgrade antenna usage for AP VIFs when all - * connected peers are idle. Only valid for multi-radio platforms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_USES_ONE_ANTENNA_WHEN_PEERS_IDLE 0x08E4 - -/******************************************************************************* - * NAME : deprecated_unifiUpdateAntennaCapabilitiesWhenScanning - * PSID : 2277 (0x08E5) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Specify whether antenna scan activities will be allowed to cause an - * update of VIF capability. Only valid for multi-radio platforms. WARNING: - * Changing this value after system start-up will have no effect. - *******************************************************************************/ -#define SLSI_PSID_DEPRECATED_UNIFI_UPDATE_ANTENNA_CAPABILITIES_WHEN_SCANNING 0x08E5 - -/******************************************************************************* - * NAME : UnifiPreferredAntennaBitmap - * PSID : 2278 (0x08E6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Specify the preferred antenna(s) to use. A value of 0 means that the FW - * will decide on the antenna(s) to use. Only valid for multi-radio - * platforms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PREFERRED_ANTENNA_BITMAP 0x08E6 - -/******************************************************************************* - * NAME : UnifiMaxConcurrentMaCs - * PSID : 2279 (0x08E7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2 - * DESCRIPTION : - * Specify the maximum number of MACs that may be used for the platform. For - * multi-MAC platforms that value *could* be greater than 1. WARNING: - * Changing this value after system start-up will have no effect. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAX_CONCURRENT_MA_CS 0x08E7 - -/******************************************************************************* - * NAME : UnifiLoadDpdLutPerRadio - * PSID : 2280 (0x08E8) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 147 - * MAX : 147 - * DEFAULT : - * DESCRIPTION : - * Write a static DPD LUT to the FW, read DPD LUT from hardware (for devices - * that support multiple radios) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LOAD_DPD_LUT_PER_RADIO 0x08E8 - -/******************************************************************************* - * NAME : UnifiOverrideDpdLutPerRadio - * PSID : 2281 (0x08E9) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 147 - * MAX : 147 - * DEFAULT : - * DESCRIPTION : - * Write a DPD LUT directly to the HW (for devices that support multiple - * radios) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_DPD_LUT_PER_RADIO 0x08E9 - -/******************************************************************************* - * NAME : UnifiRoamDeauthReason - * PSID : 2294 (0x08F6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 3 - * DESCRIPTION : - * A deauthentication reason for which the STA will trigger a roaming scan - * rather than disconnect directly. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_DEAUTH_REASON 0x08F6 - -/******************************************************************************* - * NAME : UnifiCuRoamfactor - * PSID : 2295 (0x08F7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Table allocating CUfactor to Channel Utilisation values range. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CU_ROAMFACTOR 0x08F7 - -/******************************************************************************* - * NAME : UnifiRoamCuHighLowPoints - * PSID : 2296 (0x08F8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Table allocating the high and low points for computing the linear - * CUfactor. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_CU_HIGH_LOW_POINTS 0x08F8 - -/******************************************************************************* - * NAME : UnifiRoamRssiHighLowPoints - * PSID : 2297 (0x08F9) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Table allocating the high and low points for computing the linear RSSI - * factor. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_RSSI_HIGH_LOW_POINTS 0x08F9 - -/******************************************************************************* - * NAME : UnifiRoamRssiBoost - * PSID : 2298 (0x08FA) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * The value in dBm of the RSSI boost for each band - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_RSSI_BOOST 0x08FA - -/******************************************************************************* - * NAME : UnifiRoamTrackingScanPeriod - * PSID : 2299 (0x08FB) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 1 - * MAX : 4294967295 - * DEFAULT : 5000000 - * DESCRIPTION : - * The scan period for tracking not yet suitable candidate(s)(microseconds) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_TRACKING_SCAN_PERIOD 0x08FB - -/******************************************************************************* - * NAME : UnifiRoamCuLocal - * PSID : 2300 (0x08FC) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Channel utilisation for the STA VIF, value 255=100% channel utilisation. - * - used for roaming - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_CU_LOCAL 0x08FC - -/******************************************************************************* - * NAME : UnifiCuRoamScanNoCandidateDeltaTrigger - * PSID : 2301 (0x08FD) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 15 - * DESCRIPTION : - * The delta, in percentage points, to apply to unifiCuRoamScanTrigger when - * no candidate found during first cycle of cached channel soft scan, - * triggered by channel utilization. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CU_ROAM_SCAN_NO_CANDIDATE_DELTA_TRIGGER 0x08FD - -/******************************************************************************* - * NAME : UnifiRoamApSelectDeltaFactor - * PSID : 2302 (0x08FE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 20 - * DESCRIPTION : - * How much higher, in percentage points, does a candidate's score needs to - * be in order be considered an eligible candidate? A "0" value renders all - * candidates eligible. Please note this applies only to soft roams. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_AP_SELECT_DELTA_FACTOR 0x08FE - -/******************************************************************************* - * NAME : UnifiCuRoamweight - * PSID : 2303 (0x08FF) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 30 - * DESCRIPTION : - * Weight of CUfactor, in percentage points, in AP selection algorithm. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CU_ROAMWEIGHT 0x08FF - -/******************************************************************************* - * NAME : UnifiRssiRoamweight - * PSID : 2305 (0x0901) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 70 - * DESCRIPTION : - * Weight of RSSI factor, in percentage points, in AP selection algorithm. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSI_ROAMWEIGHT 0x0901 - -/******************************************************************************* - * NAME : UnifiRssiRoamfactor - * PSID : 2306 (0x0902) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Table allocating RSSIfactor to RSSI values range. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSI_ROAMFACTOR 0x0902 - -/******************************************************************************* - * NAME : UnifiRssicuRoamScanTrigger - * PSID : 2307 (0x0903) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * The current channel Averaged RSSI value below which a soft roaming scan - * shall initially start, providing high channel utilisation (see - * unifiCURoamScanTrigger). This is a table indexed by frequency band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RSSICU_ROAM_SCAN_TRIGGER 0x0903 - -/******************************************************************************* - * NAME : UnifiCuRoamScanTrigger - * PSID : 2308 (0x0904) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * BSS Load / Channel Utilisation doesn't need to be monitored more than - * every 10th Beacons. This is a table indexed by frequency band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CU_ROAM_SCAN_TRIGGER 0x0904 - -/******************************************************************************* - * NAME : UnifiRoamBssLoadMonitoringFrequency - * PSID : 2309 (0x0905) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 10 - * DESCRIPTION : - * How often, in reveived beacons, should the BSS load be monitored? - used - * for roaming - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_BSS_LOAD_MONITORING_FREQUENCY 0x0905 - -/******************************************************************************* - * NAME : UnifiRoamBlacklistSize - * PSID : 2310 (0x0906) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : entries - * MIN : 0 - * MAX : 100 - * DEFAULT : 5 - * DESCRIPTION : - * Do not remove! Read by the host! And then passed up to the framework. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_BLACKLIST_SIZE 0x0906 - -/******************************************************************************* - * NAME : UnifiCuMeasurementInterval - * PSID : 2311 (0x0907) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 1 - * MAX : 1000 - * DEFAULT : 500 - * DESCRIPTION : - * The interval in ms to perform the channel usage update - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CU_MEASUREMENT_INTERVAL 0x0907 - -/******************************************************************************* - * NAME : UnifiCurrentBssNss - * PSID : 2312 (0x0908) - * PER INTERFACE?: NO - * TYPE : unifiAntennaMode - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * specifies current AP antenna mode: 0 = SISO, 1 = MIMO (2x2), 2 = MIMO - * (3x3), 3 = MIMO (4x4) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CURRENT_BSS_NSS 0x0908 - -/******************************************************************************* - * NAME : UnifiApMimoUsed - * PSID : 2313 (0x0909) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * AP uses MU-MIMO - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_MIMO_USED 0x0909 - -/******************************************************************************* - * NAME : UnifiRoamEapolTimeout - * PSID : 2314 (0x090A) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 10 - * DESCRIPTION : - * Maximum time, in seconds, allowed for an offloaded Eapol (4 way - * handshake). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_EAPOL_TIMEOUT 0x090A - -/******************************************************************************* - * NAME : UnifiRoamingCount - * PSID : 2315 (0x090B) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Number of roams - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAMING_COUNT 0x090B - -/******************************************************************************* - * NAME : UnifiRoamingAkm - * PSID : 2316 (0x090C) - * PER INTERFACE?: NO - * TYPE : unifiRoamingAKM - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * specifies current AKM 0 = None 1 = OKC 2 = FT (FT_1X) 3 = PSK 4 = FT_PSK - * 5 = PMKSA Caching - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAMING_AKM 0x090C - -/******************************************************************************* - * NAME : UnifiCurrentBssBandwidth - * PSID : 2317 (0x090D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Current bandwidth the STA is operating on channel_bw_20_mhz = 20, - * channel_bw_40_mhz = 40, channel_bw_80_mhz = 80, channel_bw_160_mhz = 160 - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CURRENT_BSS_BANDWIDTH 0x090D - -/******************************************************************************* - * NAME : UnifiCurrentBssChannelFrequency - * PSID : 2318 (0x090E) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Centre frequency for the connected channel - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CURRENT_BSS_CHANNEL_FREQUENCY 0x090E - -/******************************************************************************* - * NAME : UnifiLoggerEnabled - * PSID : 2320 (0x0910) - * PER INTERFACE?: NO - * TYPE : unifiWifiLogger - * MIN : 0 - * MAX : 255 - * DEFAULT : 1 - * DESCRIPTION : - * Enable reporting of the following events for Android logging: - firmware - * connectivity events - fate of management frames sent by the host through - * the MLME SAP It can take the following values: - 0: reporting for non - * mandetory triggers disabled. EAPOL, security, btm frames and roam - * triggers are reported. - 1: partial reporting is enabled. Beacons frames - * will not be reported. - 2: full reporting is enabled. Beacons frames are - * included. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LOGGER_ENABLED 0x0910 - -/******************************************************************************* - * NAME : UnifiMaPacketFateEnabled - * PSID : 2321 (0x0911) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enable reporting of the fate of the TX packets sent by the host.This mib - * value will be updated if "unifiRameUpdateMibs" mib is toggled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MA_PACKET_FATE_ENABLED 0x0911 - -/******************************************************************************* - * NAME : unifiStaVifLinkNss - * PSID : 2324 (0x0914) - * PER INTERFACE?: NO - * TYPE : unifiAntennaMode - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Sta Vif (Not P2P) while connected to an AP. - * Specifies the max number of NSS that the link can use : 0 = SISO, 1 = MIMO (2x2), 2 = MIMO - * (3x3), 3 = MIMO (4x4) - *******************************************************************************/ -/* TODO : MIB autogen */ -#define SLSI_PSID_UNIFI_STA_VIF_LINK_NSS 0x0914 - -/******************************************************************************* - * NAME : UnifiFrameRxCounters - * PSID : 2326 (0x0916) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Frame RX Counters used by the host. These are required by MCD. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FRAME_RX_COUNTERS 0x0916 - -/******************************************************************************* - * NAME : UnifiFrameTxCounters - * PSID : 2327 (0x0917) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Frame TX Counters used by the host. These are required by MCD. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FRAME_TX_COUNTERS 0x0917 - -/******************************************************************************* - * NAME : UnifiLaaNssSpeculationIntervalSlotTime - * PSID : 2330 (0x091A) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 300 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the repeatable amount of time, - * in ms, that firmware will start to send speculation frames for spatial - * streams. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_NSS_SPECULATION_INTERVAL_SLOT_TIME 0x091A - -/******************************************************************************* - * NAME : UnifiLaaNssSpeculationIntervalSlotMaxNum - * PSID : 2331 (0x091B) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 5 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the maximum number of - * speculation time slot for spatial stream. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_NSS_SPECULATION_INTERVAL_SLOT_MAX_NUM 0x091B - -/******************************************************************************* - * NAME : UnifiLaaBwSpeculationIntervalSlotTime - * PSID : 2332 (0x091C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 300 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the repeatable amount of time, - * in ms, that firmware will start to send speculation frames for bandwidth. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_BW_SPECULATION_INTERVAL_SLOT_TIME 0x091C - -/******************************************************************************* - * NAME : UnifiLaaBwSpeculationIntervalSlotMaxNum - * PSID : 2333 (0x091D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 8 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the maximum number of - * speculation time slot for bandwidth. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_BW_SPECULATION_INTERVAL_SLOT_MAX_NUM 0x091D - -/******************************************************************************* - * NAME : UnifiLaaMcsSpeculationIntervalSlotTime - * PSID : 2334 (0x091E) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 100 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the repeatable amount of time, - * in ms, that firmware will start to send speculation frames for MCS or - * rate index. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_MCS_SPECULATION_INTERVAL_SLOT_TIME 0x091E - -/******************************************************************************* - * NAME : UnifiLaaMcsSpeculationIntervalSlotMaxNum - * PSID : 2335 (0x091F) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the maximum number of - * speculation time slot for MCS or rate index. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_MCS_SPECULATION_INTERVAL_SLOT_MAX_NUM 0x091F - -/******************************************************************************* - * NAME : UnifiLaaGiSpeculationIntervalSlotTime - * PSID : 2336 (0x0920) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 100 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the repeatable amount of time, - * in ms, that firmware will start to send speculation frames for guard - * interval. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_GI_SPECULATION_INTERVAL_SLOT_TIME 0x0920 - -/******************************************************************************* - * NAME : UnifiLaaGiSpeculationIntervalSlotMaxNum - * PSID : 2337 (0x0921) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 50 - * DESCRIPTION : - * For Link Adaptation Algorithm. It defines the maximum number of - * speculation time slot for guard interval. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_GI_SPECULATION_INTERVAL_SLOT_MAX_NUM 0x0921 - -/******************************************************************************* - * NAME : UnifiLaaTxDiversityBeamformEnabled - * PSID : 2350 (0x092E) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * For Link Adaptation Algorithm. It is used to enable or disable TX - * beamformer functionality. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_TX_DIVERSITY_BEAMFORM_ENABLED 0x092E - -/******************************************************************************* - * NAME : UnifiLaaTxDiversityBeamformMinMcs - * PSID : 2351 (0x092F) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2 - * DESCRIPTION : - * For Link Adaptation Algorithm. TX Beamform is applied when MCS is same or - * larger than this threshold value. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_TX_DIVERSITY_BEAMFORM_MIN_MCS 0x092F - -/******************************************************************************* - * NAME : UnifiLaaTxDiversityFixMode - * PSID : 2352 (0x0930) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * For Link Adaptation Algorithm. It is used to fix TX diversity mode. With - * two antennas available and only one spatial stream used, then one of the - * following modes can be selected: - 0 : Not fixed. Tx diversity mode is - * automatically selected by LAA. - 1 : CDD fixed mode - 2 : Beamforming - * fixed mode - 3 : STBC fixed mode - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_TX_DIVERSITY_FIX_MODE 0x0930 - -/******************************************************************************* - * NAME : UnifiLaaProtectionConfigOverride - * PSID : 2356 (0x0934) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 6 - * DESCRIPTION : - * Overrides the default Protection configuration. Only valid flags are - * DPIF_PEER_INFO_PROTECTION_TXOP_AMPDU and - * DPIF_PEER_INFO_PROTECTION_ALLOWED. Default allows protection code to work - * out the rules based on VIF configuration. If - * DPIF_PEER_INFO_PROTECTION_ALLOWED is unset, all protection, for this vif, - * is disabled. If DPIF_PEER_INFO_PROTECTION_TXOP_AMPDU is unset then, for - * the specified vif, the first A-MPDU in the TxOp is no longer protected. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LAA_PROTECTION_CONFIG_OVERRIDE 0x0934 - -/******************************************************************************* - * NAME : UnifiRateStatsRtsErrorCount - * PSID : 2358 (0x0936) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of successive RTS failures. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RATE_STATS_RTS_ERROR_COUNT 0x0936 - -/******************************************************************************* - * NAME : UnifiCsrOnlyEifsDuration - * PSID : 2362 (0x093A) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : 12 - * DESCRIPTION : - * Specifies time that is used for EIFS. A value of 0 causes the build in - * value to be used. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CSR_ONLY_EIFS_DURATION 0x093A - -/******************************************************************************* - * NAME : UnifiOverrideDefaultBetxopForHt - * PSID : 2364 (0x093C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 171 - * DESCRIPTION : - * When set to non-zero value then this will override the BE TXOP for 11n - * and higher modulations (in 32 usec units) to the value specified here. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_DEFAULT_BETXOP_FOR_HT 0x093C - -/******************************************************************************* - * NAME : UnifiOverrideDefaultBetxop - * PSID : 2365 (0x093D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 78 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: When set to - * non-zero value then this will override the BE TXOP for 11g (in 32 usec - * units) to the value specified here. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_DEFAULT_BETXOP 0x093D - -/******************************************************************************* - * NAME : UnifiRxabbTrimSettings - * PSID : 2366 (0x093E) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Various settings to change RX ABB filter trim behavior. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RXABB_TRIM_SETTINGS 0x093E - -/******************************************************************************* - * NAME : UnifiRadioTrimsEnable - * PSID : 2367 (0x093F) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X0FF5 - * DESCRIPTION : - * A bitmap for enabling/disabling trims at runtime. Check unifiEnabledTrims - * enum for description of the possible values. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_TRIMS_ENABLE 0x093F - -/******************************************************************************* - * NAME : UnifiRadioCcaThresholds - * PSID : 2368 (0x0940) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * The wideband CCA ED thresholds so that the CCA-ED triggers at the - * regulatory value of -62 dBm. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_CCA_THRESHOLDS 0x0940 - -/******************************************************************************* - * NAME : UnifiHardwarePlatform - * PSID : 2369 (0x0941) - * PER INTERFACE?: NO - * TYPE : unifiHardwarePlatform - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware platform. This is necessary so we can apply tweaks to specific - * revisions, even though they might be running the same baseband and RF - * chip combination. Check unifiHardwarePlatform enum for description of the - * possible values. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_HARDWARE_PLATFORM 0x0941 - -/******************************************************************************* - * NAME : UnifiForceChannelBw - * PSID : 2370 (0x0942) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Test only: Force channel bandwidth to specified value. This can also be - * used to allow emulator/silicon back to back connection to communicate at - * bandwidth other than default (20 MHz) Setting it to 0 uses the default - * bandwidth as selected by firmware channel_bw_20_mhz = 20, - * channel_bw_40_mhz = 40, channel_bw_80_mhz = 80 This mib value will be - * updated if "unifiRameUpdateMibs" mib is toggled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FORCE_CHANNEL_BW 0x0942 - -/******************************************************************************* - * NAME : UnifiDpdTrainingDuration - * PSID : 2371 (0x0943) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Duration of DPD training (in ms). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPD_TRAINING_DURATION 0x0943 - -/******************************************************************************* - * NAME : UnifiTxFtrimSettings - * PSID : 2372 (0x0944) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter frequency compensation settings - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_FTRIM_SETTINGS 0x0944 - -/******************************************************************************* - * NAME : UnifiDpdTrainPacketConfig - * PSID : 2373 (0x0945) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 8 - * MAX : 8 - * DEFAULT : - * DESCRIPTION : - * This MIB allows the dummy packets training bandwidth and rates to be - * overriden. Tipically the bandwidth would be the same as the channel - * bandwidth (for example 80 MHz packets for an 80 Mhz channel) and rates - * MCS1 and MCS5. With this MIB you can set, for example, an 80 MHz channel - * to be trained using 20 MHz bandwidth (centered or not) with MCS2 and MCS7 - * packets. The MIB index dictates what channel bandwidth the configuration - * is for (1 for 20 MHz, 2 for 40 MHz and so on). The format is: - octet 0: - * train bandwidth (this basically follows the rice_channel_bw_t enum). - - * octet 1: train primary channel position - octet 2-3: OFDM 0 rate - octet - * 4-5: OFDM 1 rate - octet 6-7: CCK rate (unused) The rates are encoded in - * host(FAPI) format, see SC-506179, section 4.41. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPD_TRAIN_PACKET_CONFIG 0x0945 - -/******************************************************************************* - * NAME : UnifiTxPowerTrimCommonConfig - * PSID : 2374 (0x0946) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 3 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Common transmitter power trim settings - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_POWER_TRIM_COMMON_CONFIG 0x0946 - -/******************************************************************************* - * NAME : UnifiIqDebugEnabled - * PSID : 2375 (0x0947) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Send IQ capture data to host for IQ debug - *******************************************************************************/ -#define SLSI_PSID_UNIFI_IQ_DEBUG_ENABLED 0x0947 - -/******************************************************************************* - * NAME : UnifiCoexDebugOverrideBt - * PSID : 2425 (0x0979) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables overriding of all BT activities by WLAN. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_COEX_DEBUG_OVERRIDE_BT 0x0979 - -/******************************************************************************* - * NAME : UnifiLteMailbox - * PSID : 2430 (0x097E) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 36 - * MAX : 40 - * DEFAULT : - * DESCRIPTION : - * Set modem status to simulate lte status updates. See SC-505775-SP for API - * description. Defined as array of uint32 represented by the octet string - * FOR TEST PURPOSES ONLY - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_MAILBOX 0x097E - -/******************************************************************************* - * NAME : UnifiLteMwsSignal - * PSID : 2431 (0x097F) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Set modem status to simulate lte status updates. See SC-505775-SP for API - * description. See unifiLteSignalsBitField for enum bitmap. FOR TEST - * PURPOSES ONLY - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_MWS_SIGNAL 0x097F - -/******************************************************************************* - * NAME : UnifiLteEnableChannelAvoidance - * PSID : 2432 (0x0980) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables channel avoidance scheme for LTE Coex - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_ENABLE_CHANNEL_AVOIDANCE 0x0980 - -/******************************************************************************* - * NAME : UnifiLteEnablePowerBackoff - * PSID : 2433 (0x0981) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables power backoff scheme for LTE Coex - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_ENABLE_POWER_BACKOFF 0x0981 - -/******************************************************************************* - * NAME : UnifiLteEnableTimeDomain - * PSID : 2434 (0x0982) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables TDD scheme for LTE Coex - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_ENABLE_TIME_DOMAIN 0x0982 - -/******************************************************************************* - * NAME : UnifiLteEnableLteCoex - * PSID : 2435 (0x0983) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables LTE Coex support - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_ENABLE_LTE_COEX 0x0983 - -/******************************************************************************* - * NAME : UnifiLteBand40PowerBackoffChannelMask - * PSID : 2436 (0x0984) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 3 - * DESCRIPTION : - * Channel Mask defining channels on which to apply power backoff when LTE - * operating on Band40. Defined as a 16 bit bitmask, as only 2G4 channels - * are impacted by this feature. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_BAND40_POWER_BACKOFF_CHANNEL_MASK 0x0984 - -/******************************************************************************* - * NAME : UnifiLteBand40PowerBackoffRsrpLow - * PSID : 2437 (0x0985) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dBm - * MIN : -140 - * MAX : -77 - * DEFAULT : -100 - * DESCRIPTION : - * WLAN Power Reduction shall be applied when RSRP of LTE operating on band - * 40 falls below this level - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_BAND40_POWER_BACKOFF_RSRP_LOW 0x0985 - -/******************************************************************************* - * NAME : UnifiLteBand40PowerBackoffRsrpHigh - * PSID : 2438 (0x0986) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dBm - * MIN : -140 - * MAX : -77 - * DEFAULT : -95 - * DESCRIPTION : - * WLAN Power Reduction shall be restored when RSRP of LTE operating on band - * 40 climbs above this level - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_BAND40_POWER_BACKOFF_RSRP_HIGH 0x0986 - -/******************************************************************************* - * NAME : UnifiLteBand40PowerBackoffRsrpAveragingAlpha - * PSID : 2439 (0x0987) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : percentage - * MIN : 0 - * MAX : 65535 - * DEFAULT : 50 - * DESCRIPTION : - * Weighting applied when calculaing the average RSRP when considering Power - * Back Off Specifies the percentage weighting (alpha) to give to the most - * recent value when calculating the moving average. ma_new = alpha * - * new_sample + (1-alpha) * ma_old. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_BAND40_POWER_BACKOFF_RSRP_AVERAGING_ALPHA 0x0987 - -/******************************************************************************* - * NAME : UnifiLteSetChannel - * PSID : 2440 (0x0988) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Enables LTE Coex support - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_SET_CHANNEL 0x0988 - -/******************************************************************************* - * NAME : UnifiLteSetPowerBackoff - * PSID : 2441 (0x0989) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * MIB to force WLAN Power Backoff for LTE COEX testing purposes - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_SET_POWER_BACKOFF 0x0989 - -/******************************************************************************* - * NAME : UnifiLteSetTddDebugMode - * PSID : 2442 (0x098A) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * MIB to enable LTE TDD COEX simulation for testing purposes - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_SET_TDD_DEBUG_MODE 0x098A - -/******************************************************************************* - * NAME : UnifiApScanAbsenceDuration - * PSID : 2480 (0x09B0) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : beacon intervals - * MIN : 0 - * MAX : 65535 - * DEFAULT : 7 - * DESCRIPTION : - * Duration of the Absence time to use when protecting AP VIFs from scan - * operations. A value of 0 disables the feature. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_SCAN_ABSENCE_DURATION 0x09B0 - -/******************************************************************************* - * NAME : UnifiApScanAbsencePeriod - * PSID : 2481 (0x09B1) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : beacon intervals - * MIN : 0 - * MAX : 65535 - * DEFAULT : 14 - * DESCRIPTION : - * Period of the Absence/Presence times cycles to use when protecting AP - * VIFs from scan operations. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_SCAN_ABSENCE_PERIOD 0x09B1 - -/******************************************************************************* - * NAME : UnifiMlmestaKeepAliveTimeoutCheck - * PSID : 2485 (0x09B5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 5 - * DESCRIPTION : - * DO NOT SET TO A VALUE HIGHER THAN THE TIMEOUT. How long before keepalive - * timeout to start polling, in seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLMESTA_KEEP_ALIVE_TIMEOUT_CHECK 0x09B5 - -/******************************************************************************* - * NAME : UnifiMlmeapKeepAliveTimeoutCheck - * PSID : 2486 (0x09B6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 5 - * DESCRIPTION : - * DO NOT SET TO A VALUE HIGHER THAN THE TIMEOUT. How long before keepalive - * timeout to start polling, in seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLMEAP_KEEP_ALIVE_TIMEOUT_CHECK 0x09B6 - -/******************************************************************************* - * NAME : UnifiMlmegoKeepAliveTimeoutCheck - * PSID : 2487 (0x09B7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 5 - * DESCRIPTION : - * DO NOT SET TO A VALUE HIGHER THAN THE TIMEOUT. How long before keepalive - * timeout to start polling, in seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLMEGO_KEEP_ALIVE_TIMEOUT_CHECK 0x09B7 - -/******************************************************************************* - * NAME : UnifiBssMaxIdlePeriod - * PSID : 2488 (0x09B8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : second - * MIN : 0 - * MAX : 300 - * DEFAULT : 300 - * DESCRIPTION : - * BSS Idle MAX Period. Used to cap the value coming from BSS Max Idle - * Period IE, in seconds - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BSS_MAX_IDLE_PERIOD 0x09B8 - -/******************************************************************************* - * NAME : UnifiIdlemodeListenIntervalSkippingDtim - * PSID : 2495 (0x09BF) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : DTIM intervals - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X00054645 - * DESCRIPTION : - * Listen interval of beacons when in single-vif power saving mode, - * receiving DTIMs is enabled and idle mode enabled. No DTIMs are skipped - * during MVIF operation. A maximum of the listen interval beacons are - * skipped, which may be less than the number of DTIMs that can be skipped. - * The value is a lookup table for DTIM counts. Each 4bits, in LSB order, - * represent DTIM1, DTIM2, DTIM3, DTIM4, DTIM5, (unused). This key is only - * used for STA VIF, connected to an AP. For P2P group client intervals, - * refer to unifiIdlemodeP2PListenIntervalSkippingDTIM, PSID=2496. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_IDLEMODE_LISTEN_INTERVAL_SKIPPING_DTIM 0x09BF - -/******************************************************************************* - * NAME : UnifiIdlemodeP2PListenIntervalSkippingDtim - * PSID : 2496 (0x09C0) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : DTIM intervals - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X00000002 - * DESCRIPTION : - * Listen interval of beacons when in single-vif, P2P client power saving - * mode,receiving DTIMs and idle mode enabled. No DTIMs are skipped during - * MVIF operation. A maximum of (listen interval - 1) beacons are skipped, - * which may be less than the number of DTIMs that can be skipped. The value - * is a lookup table for DTIM counts. Each 4bits, in LSB order, represent - * DTIM1, DTIM2, DTIM3, DTIM4, DTIM5, (unused). This key is only used for - * P2P group client. For STA connected to an AP, refer to - * unifiIdlemodeListenIntervalSkippingDTIM, PSID=2495. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_IDLEMODE_P2_PLISTEN_INTERVAL_SKIPPING_DTIM 0x09C0 - -/******************************************************************************* - * NAME : UnifiApIdleModeEnabled - * PSID : 2497 (0x09C1) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables AP Idle mode which can transmit beacons in MIFLess mode, if - * softAP is active, and there has been no activity for a time. This mib has - * priority over unifiIdleModeLiteEnabled. If unifiAPIdleEnabled is enabled, - * Idle Mode Lite won't be activated. This mib value will be runtime - * (post-wlan enable) applied only if "unifiRameUpdateMibs" mib is toggled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_IDLE_MODE_ENABLED 0x09C1 - -/******************************************************************************* - * NAME : UnifiFastPowerSaveTimeout - * PSID : 2500 (0x09C4) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : microseconds - * MIN : 0 - * MAX : 2147483647 - * DEFAULT : 400000 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: UniFi - * implements a proprietary power management mode called Fast Power Save - * that balances network performance against power consumption. In this mode - * UniFi delays entering power save mode until it detects that there has - * been no exchange of data for the duration of time specified. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FAST_POWER_SAVE_TIMEOUT 0x09C4 - -/******************************************************************************* - * NAME : UnifiFastPowerSaveTimeoutSmall - * PSID : 2501 (0x09C5) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : microseconds - * MIN : 0 - * MAX : 2147483647 - * DEFAULT : 200000 - * DESCRIPTION : - * UniFi implements a proprietary power management mode called Fast Power - * Save that balances network performance against power consumption. In this - * mode UniFi delays entering power save mode until it detects that there - * has been no exchange of data for the duration of time specified. The - * unifiFastPowerSaveTimeOutSmall aims to improve the power consumption by - * setting a lower bound for the Fast Power Save Timeout. If set with a - * value above unifiFastPowerSaveTimeOut it will default to - * unifiFastPowerSaveTimeOut. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FAST_POWER_SAVE_TIMEOUT_SMALL 0x09C5 - -/******************************************************************************* - * NAME : UnifiMlmestaKeepAliveTimeout - * PSID : 2502 (0x09C6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 2147 - * DEFAULT : 30 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Timeout - * before disconnecting in seconds. 0 = Disabled. Capped to greater than 6 - * seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLMESTA_KEEP_ALIVE_TIMEOUT 0x09C6 - -/******************************************************************************* - * NAME : UnifiMlmeapKeepAliveTimeout - * PSID : 2503 (0x09C7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 2147 - * DEFAULT : 10 - * DESCRIPTION : - * Timeout before disconnecting in seconds. 0 = Disabled. Capped to greater - * than 6 seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLMEAP_KEEP_ALIVE_TIMEOUT 0x09C7 - -/******************************************************************************* - * NAME : UnifiMlmegoKeepAliveTimeout - * PSID : 2504 (0x09C8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 2147 - * DEFAULT : 10 - * DESCRIPTION : - * Timeout before disconnecting in seconds. 0 = Disabled. Capped to greater - * than 6 seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLMEGO_KEEP_ALIVE_TIMEOUT 0x09C8 - -/******************************************************************************* - * NAME : UnifiStaRouterAdvertisementMinimumIntervalToForward - * PSID : 2505 (0x09C9) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 60 - * MAX : 4294967285 - * DEFAULT : 60 - * DESCRIPTION : - * STA Mode: Minimum interval to forward Router Advertisement frames to - * Host. Minimum value = 60 secs. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STA_ROUTER_ADVERTISEMENT_MINIMUM_INTERVAL_TO_FORWARD 0x09C9 - -/******************************************************************************* - * NAME : UnifiRoamConnectionQualityCheckWaitAfterConnect - * PSID : 2506 (0x09CA) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : ms - * MIN : 0 - * MAX : 65535 - * DEFAULT : 200 - * DESCRIPTION : - * The amount of time a STA will wait after connection before starting to - * check the MLME-installed connection quality trigger thresholds - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ROAM_CONNECTION_QUALITY_CHECK_WAIT_AFTER_CONNECT 0x09CA - -/******************************************************************************* - * NAME : UnifiApBeaconMaxDrift - * PSID : 2507 (0x09CB) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0XFFFF - * DESCRIPTION : - * The maximum drift in microseconds we will allow for each beacon sent when - * we're trying to move it to get a 50% duty cycle between GO and STA in - * multiple VIF scenario. We'll delay our TX beacon by a maximum of this - * value until we reach our target TBTT. We have 3 possible cases for this - * value: a) ap_beacon_max_drift = 0x0000 - Feature disabled b) - * ap_beacon_max_drift between 0x0001 and 0xFFFE - Each time we transmit the - * beacon we'll move it a little bit forward but never more than this. (Not - * implemented yet) c) ap_beacon_max_drift = 0xFFFF - Move the beacon to the - * desired position in one shot. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AP_BEACON_MAX_DRIFT 0x09CB - -/******************************************************************************* - * NAME : UnifiBssMaxIdlePeriodEnabled - * PSID : 2508 (0x09CC) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * If set STA will configure keep-alive with options specified in a received - * BSS max idle period IE - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BSS_MAX_IDLE_PERIOD_ENABLED 0x09CC - -/******************************************************************************* - * NAME : UnifiVifIdleMonitorTime - * PSID : 2509 (0x09CD) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : second - * MIN : 0 - * MAX : 1800 - * DEFAULT : 1 - * DESCRIPTION : - * In Fast Power Save mode, the STA will decide whether it is idle based on - * monitoring its traffic class. If the traffic class is continuously - * "occasional" for equal or longer than the specified value (in seconds), - * then the VIF is marked as idle. Traffic class monitoring is based on the - * interval specified in the "unifiExitPowerSavePeriod" MIB - *******************************************************************************/ -#define SLSI_PSID_UNIFI_VIF_IDLE_MONITOR_TIME 0x09CD - -/******************************************************************************* - * NAME : UnifiDisableLegacyPowerSave - * PSID : 2510 (0x09CE) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: This affects - * Station VIF power save behaviour. Setting it to true will disable legacy - * power save (i.e. we wil use fast power save to retrieve data) Note that - * actually disables full power save mode (i.e sending trigger to retrieve - * frames which will be PS-POLL for legacy and QOS-NULL for UAPSD) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DISABLE_LEGACY_POWER_SAVE 0x09CE - -/******************************************************************************* - * NAME : UnifiDebugForceActive - * PSID : 2511 (0x09CF) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Force station - * power save mode to be active (when scheduled). VIF scheduling, coex and - * other non-VIF specific reasons could still force power save on the VIF. - * Applies to all VIFs of type station (includes P2P client). Changes to the - * mib will only get applied after next host/mlme power management request. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEBUG_FORCE_ACTIVE 0x09CF - -/******************************************************************************* - * NAME : UnifiStationActivityIdleTime - * PSID : 2512 (0x09D0) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : milliseconds - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 500 - * DESCRIPTION : - * Time since last station activity when it can be considered to be idle. - * Only used in SoftAP mode when determining if all connected stations are - * idle (not active). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STATION_ACTIVITY_IDLE_TIME 0x09D0 - -/******************************************************************************* - * NAME : UnifiDmsEnabled - * PSID : 2513 (0x09D1) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables Directed Multicast Service (DMS) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DMS_ENABLED 0x09D1 - -/******************************************************************************* - * NAME : UnifiPowerManagementDelayTimeout - * PSID : 2514 (0x09D2) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : microseconds - * MIN : 0 - * MAX : 2147483647 - * DEFAULT : 30000 - * DESCRIPTION : - * When UniFi enters power save mode it signals the new state by setting the - * power management bit in the frame control field of a NULL frame. It then - * remains active for the period since the previous unicast reception, or - * since the transmission of the NULL frame, whichever is later. This entry - * controls the maximum time during which UniFi will continue to listen for - * data. This allows any buffered data on a remote device to be cleared. - * Specifies an upper limit on the timeout. UniFi internally implements a - * proprietary algorithm to adapt the timeout depending upon the - * situation.This is used by firmware when current station VIF is only - * station VIF which can be scheduled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_POWER_MANAGEMENT_DELAY_TIMEOUT 0x09D2 - -/******************************************************************************* - * NAME : UnifiApsdServicePeriodTimeout - * PSID : 2515 (0x09D3) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : 20000 - * DESCRIPTION : - * During Unscheduled Automated Power Save Delivery (U-APSD), UniFi may - * trigger a service period in order to fetch data from the access point. - * The service period is normally terminated by a frame from the access - * point with the EOSP (End Of Service Period) flag set, at which point - * UniFi returns to sleep. However, if the access point is temporarily - * inaccessible, UniFi would stay awake indefinitely. Specifies a timeout - * starting from the point where the trigger frame has been sent. If the - * timeout expires and no data has been received from the access point, - * UniFi will behave as if the service period had been ended normally and - * return to sleep. This timeout takes precedence over - * unifiPowerSaveExtraListenTime if both would otherwise be applicable. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_APSD_SERVICE_PERIOD_TIMEOUT 0x09D3 - -/******************************************************************************* - * NAME : UnifiConcurrentPowerManagementDelayTimeout - * PSID : 2516 (0x09D4) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : microseconds - * MIN : 0 - * MAX : 2147483647 - * DEFAULT : 10000 - * DESCRIPTION : - * When UniFi enters power save mode it signals the new state by setting the - * power management bit in the frame control field of a NULL frame. It then - * remains active for the period since the previous unicast reception, or - * since the transmission of the NULL frame, whichever is later. This entry - * controls the maximum time during which UniFi will continue to listen for - * data. This allows any buffered data on a remote device to be cleared. - * This is same as unifiPowerManagementDelayTimeout but this value is - * considered only when we are doing multivif operations and other VIFs are - * waiting to be scheduled.Note that firmware automatically chooses one of - * unifiPowerManagementDelayTimeout and - * unifiConcurrentPowerManagementDelayTimeout depending upon the current - * situation.It is sensible to set unifiPowerManagementDelayTimeout to be - * always more thanunifiConcurrentPowerManagementDelayTimeout. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CONCURRENT_POWER_MANAGEMENT_DELAY_TIMEOUT 0x09D4 - -/******************************************************************************* - * NAME : UnifiStationQosInfo - * PSID : 2517 (0x09D5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * QoS capability for a non-AP Station, and is encoded as per IEEE 802.11 - * QoS Capability. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STATION_QOS_INFO 0x09D5 - -/******************************************************************************* - * NAME : UnifiListenIntervalSkippingDtim - * PSID : 2518 (0x09D6) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : DTIM intervals - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X000A89AA - * DESCRIPTION : - * Listen interval of beacons when in single-vif power saving mode,receiving - * DTIMs is enabled and idle mode disabled. No DTIMs are skipped during MVIF - * operation. A maximum of the listen interval beacons are skipped, which - * may be less than the number of DTIMs that can be skipped. The value is a - * lookup table for DTIM counts. Each 4bits, in LSB order, represent DTIM1, - * DTIM2, DTIM3, DTIM4, DTIM5, (unused). This key is only used for STA VIF, - * connected to an AP. For P2P group client intervals, refer to - * unifiP2PListenIntervalSkippingDTIM, PSID=2523. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LISTEN_INTERVAL_SKIPPING_DTIM 0x09D6 - -/******************************************************************************* - * NAME : UnifiListenInterval - * PSID : 2519 (0x09D7) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 10 - * DESCRIPTION : - * Association request listen interval parameter in beacon intervals. Not - * used for any other purpose. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LISTEN_INTERVAL 0x09D7 - -/******************************************************************************* - * NAME : UnifiLegacyPsPollTimeout - * PSID : 2520 (0x09D8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : 15000 - * DESCRIPTION : - * Time we try to stay awake after sending a PS-POLL to receive data. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LEGACY_PS_POLL_TIMEOUT 0x09D8 - -/******************************************************************************* - * NAME : UnifiBeaconSkippingControl - * PSID : 2521 (0x09D9) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X00010103 - * DESCRIPTION : - * Control beacon skipping behaviour within firmware with bit flags. 1 - * defines enabled, with 0 showing the case disabled. If beacon skipping is - * enabled, further determine if DTIM beacons can be skipped, or only - * non-DTIM beacons. The following applies: bit 0: station skipping on host - * suspend bit 1: station skipping on host awake bit 2: station skipping on - * LCD on bit 3: station skipping with multivif bit 4: station skipping with - * BT active. bit 8: station skip dtim on host suspend bit 9: station skip - * dtim on host awake bit 10: station skip dtim on LCD on bit 11: station - * skip dtim on multivif bit 12: station skip dtim with BT active bit 16: - * p2p-gc skipping on host suspend bit 17: p2p-gc skipping on host awake bit - * 18: p2p-gc skipping on LCD on bit 19: p2p-gc skipping with multivif bit - * 20: p2p-gc skipping with BT active bit 24: p2p-gc skip dtim on host - * suspend bit 25: p2p-gc skip dtim on host awake bit 26: p2p-gc skip dtim - * on LCD on bit 27: p2p-gc skip dtim on multivif bit 28: p2p-gc skip dtim - * with BT active - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BEACON_SKIPPING_CONTROL 0x09D9 - -/******************************************************************************* - * NAME : UnifiTogglePowerDomain - * PSID : 2522 (0x09DA) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Toggle WLAN power domain when entering dorm mode (deep sleep). When - * entering deep sleep and this value it true, then the WLAN power domain is - * disabled for the deep sleep duration. When false, the power domain is - * left turned on. This is to work around issues with WLAN rx, and is - * considered temporary until the root cause is found and fixed. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TOGGLE_POWER_DOMAIN 0x09DA - -/******************************************************************************* - * NAME : UnifiP2PListenIntervalSkippingDtim - * PSID : 2523 (0x09DB) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : DTIM intervals - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X00000002 - * DESCRIPTION : - * Listen interval of beacons when in single-vif, P2P client power saving - * mode,receiving DTIMs and idle mode disabled. No DTIMs are skipped during - * MVIF operation. A maximum of (listen interval - 1) beacons are skipped, - * which may be less than the number of DTIMs that can be skipped. The value - * is a lookup table for DTIM counts. Each 4bits, in LSB order, represent - * DTIM1, DTIM2, DTIM3, DTIM4, DTIM5, (unused). This key is only used for - * P2P group client. For STA connected to an AP, refer to - * unifiListenIntervalSkippingDTIM, PSID=2518. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_P2_PLISTEN_INTERVAL_SKIPPING_DTIM 0x09DB - -/******************************************************************************* - * NAME : UnifiFragmentationDuration - * PSID : 2524 (0x09DC) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * A limit on transmission time for a data frame. If the data payload would - * take longer than unifiFragmentationDuration to transmit, UniFi will - * attempt to fragment the frame to ensure that the data portion of each - * fragment is within the limit. The limit imposed by the fragmentation - * threshold is also respected, and no more than 16 fragments may be - * generated. If the value is zero no limit is imposed. The value may be - * changed dynamically during connections. Note that the limit is a - * guideline and may not always be respected. In particular, the data rate - * is finalised after fragmentation in order to ensure responsiveness to - * conditions, the calculation is not performed to high accuracy, and octets - * added during encryption are not included in the duration calculation. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FRAGMENTATION_DURATION 0x09DC - -/******************************************************************************* - * NAME : UnifiIdleModeLiteEnabled - * PSID : 2526 (0x09DE) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables Idle Mode Lite, if softAP is active, and there has been no - * activity for a time. Idle mode lite should not be active if host has sent - * a command to change key. This mib value will be runtime (post-wlan - * enable) applied only if "unifiRameUpdateMibs" mib is toggled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_IDLE_MODE_LITE_ENABLED 0x09DE - -/******************************************************************************* - * NAME : UnifiIdleModeEnabled - * PSID : 2527 (0x09DF) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enables Idle Mode, if single vif station is active or there is no vif, - * and there has been no activity for a time. This mib value will be runtime - * (post-wlan enable) applied if only "unifiRameUpdateMibs" mib is toggled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_IDLE_MODE_ENABLED 0x09DF - -/******************************************************************************* - * NAME : UnifiDtimWaitTimeout - * PSID : 2529 (0x09E1) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : 50000 - * DESCRIPTION : - * If UniFi is in power save and receives a Traffic Indication Map from its - * associated access point with a DTIM indication, it will wait a maximum - * time given by this attribute for succeeding broadcast or multicast - * traffic, or until it receives such traffic with the 'more data' - * flag clear. Any reception of broadcast or multicast traffic with the - * 'more data' flag set, or any reception of unicast data, resets - * the timeout. The timeout can be turned off by setting the value to zero; - * in that case UniFi will remain awake indefinitely waiting for broadcast - * or multicast data. Otherwise, the value should be larger than that of - * unifiPowerSaveExtraListenTime. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DTIM_WAIT_TIMEOUT 0x09E1 - -/******************************************************************************* - * NAME : UnifiListenIntervalMaxTime - * PSID : 2530 (0x09E2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : TU - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1000 - * DESCRIPTION : - * Maximum number length of time, in Time Units (1TU = 1024us), that can be - * used as a beacon listen interval. This will limit how many beacons maybe - * skipped, and affects the DTIM beacon skipping count; DTIM skipping (if - * enabled) will be such that skipped count = (unifiListenIntervalMaxTime / - * DTIM_period). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LISTEN_INTERVAL_MAX_TIME 0x09E2 - -/******************************************************************************* - * NAME : UnifiScanMaxProbeTransmitLifetime - * PSID : 2531 (0x09E3) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 1 - * MAX : 4294967295 - * DEFAULT : 64 - * DESCRIPTION : - * In TU. If non-zero, used during active scans as the maximum lifetime for - * probe requests. It is the elapsed time after the initial transmission at - * which further attempts to transmit the probe are terminated. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SCAN_MAX_PROBE_TRANSMIT_LIFETIME 0x09E3 - -/******************************************************************************* - * NAME : UnifiPowerSaveTransitionPacketThreshold - * PSID : 2532 (0x09E4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name:If VIF has - * this many packets queued/transmitted/received in last - * unifiFastPowerSaveTransitionPeriod then firmware may decide to come out - * of aggressive power save mode. This is applicable to STA/CLI and AP/GO - * VIFs. Note that this is only a guideline. Firmware internal factors may - * override this MIB. Also see unifiTrafficAnalysisPeriod and - * unifiAggressivePowerSaveTransitionPeriod. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_POWER_SAVE_TRANSITION_PACKET_THRESHOLD 0x09E4 - -/******************************************************************************* - * NAME : UnifiProbeResponseLifetime - * PSID : 2533 (0x09E5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 100 - * DESCRIPTION : - * Lifetime of proberesponse frame in unit of ms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PROBE_RESPONSE_LIFETIME 0x09E5 - -/******************************************************************************* - * NAME : UnifiProbeResponseMaxRetry - * PSID : 2534 (0x09E6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 255 - * DEFAULT : 5 - * DESCRIPTION : - * Number of retries of probe response frame. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PROBE_RESPONSE_MAX_RETRY 0x09E6 - -/******************************************************************************* - * NAME : UnifiTrafficAnalysisPeriod - * PSID : 2535 (0x09E7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : TU - * MIN : 0 - * MAX : 65535 - * DEFAULT : 200 - * DESCRIPTION : - * Period in TUs over which firmware counts number of packet - * transmitted/queued/received to make decisions like coming out of - * aggressive power save mode or setting up BlockAck. This is applicable to - * STA/CLI and AP/GO VIFs. Note that this is only a guideline. Firmware - * internal factors may override this MIB. Also see - * unifiPowerSaveTransitionPacketThreshold, - * unifiAggressivePowerSaveTransitionPeriod and - * unifiTrafficThresholdToSetupBA. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TRAFFIC_ANALYSIS_PERIOD 0x09E7 - -/******************************************************************************* - * NAME : UnifiAggressivePowerSaveTransitionPeriod - * PSID : 2536 (0x09E8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : TU - * MIN : 0 - * MAX : 65535 - * DEFAULT : 5 - * DESCRIPTION : - * Defines how many unifiExitPowerSavePeriod firmware should wait in which - * VIF had received/transmitted/queued less than - * unifiPowerSaveTransitionPacketThreshold packets - before entering - * aggressive power save mode (when not in aggressive power save mode) This - * is applicable to STA/CLI and AP/GO VIFs. Note that this is only a - * guideline. Firmware internal factors may override this MIB. Also see - * unifiPowerSaveTransitionPacketThreshold and unifiTrafficAnalysisPeriod. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AGGRESSIVE_POWER_SAVE_TRANSITION_PERIOD 0x09E8 - -/******************************************************************************* - * NAME : UnifiActiveTimeAfterMoreBit - * PSID : 2537 (0x09E9) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : TU - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 30 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: After seeing - * the "more" bit set in a message from the AP, the STA will goto active - * mode for this duration of time. After this time, traffic information is - * evaluated to determine whether the STA should stay active or go to - * powersave. Setting this value to 0 means that the described functionality - * is disabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_ACTIVE_TIME_AFTER_MORE_BIT 0x09E9 - -/******************************************************************************* - * NAME : UnifiDefaultDwellTime - * PSID : 2538 (0x09EA) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 50 - * DESCRIPTION : - * Dwell time, in TU, for frames that need a response but have no dwell time - * associated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEFAULT_DWELL_TIME 0x09EA - -/******************************************************************************* - * NAME : UnifiVhtCapabilities - * PSID : 2540 (0x09EC) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 12 - * MAX : 12 - * DEFAULT : { 0XB1, 0X7A, 0X11, 0X03, 0XFA, 0XFF, 0X00, 0X00, 0XFA, 0XFF, 0X00, 0X00 } - * DESCRIPTION : - * VHT capabilities of the chip. see SC-503520-SP. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_VHT_CAPABILITIES 0x09EC - -/******************************************************************************* - * NAME : UnifiMaxVifScheduleDuration - * PSID : 2541 (0x09ED) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : TU - * MIN : 0 - * MAX : 65535 - * DEFAULT : 50 - * DESCRIPTION : - * Default time for which a non-scan VIF can be scheduled. Applies to - * multiVIF scenario. Internal firmware logic or BSS state (e.g. NOA) may - * cut short the schedule. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAX_VIF_SCHEDULE_DURATION 0x09ED - -/******************************************************************************* - * NAME : UnifiVifLongIntervalTime - * PSID : 2542 (0x09EE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : TU - * MIN : 0 - * MAX : 65535 - * DEFAULT : 60 - * DESCRIPTION : - * When the scheduler expects a VIF to schedule for time longer than this - * parameter (specified in TUs), then the VIF may come out of powersave. - * Only valid for STA VIFs. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_VIF_LONG_INTERVAL_TIME 0x09EE - -/******************************************************************************* - * NAME : UnifiDisallowSchedRelinquish - * PSID : 2543 (0x09EF) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * When enabled the VIFs will not relinquish their assigned schedules when - * they have nothing left to do. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DISALLOW_SCHED_RELINQUISH 0x09EF - -/******************************************************************************* - * NAME : UnifiRameDplaneOperationTimeout - * PSID : 2544 (0x09F0) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : milliseconds - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 1000 - * DESCRIPTION : - * Timeout for requests sent from MACRAME to Data Plane. Any value below - * 1000ms will be capped at 1000ms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RAME_DPLANE_OPERATION_TIMEOUT 0x09F0 - -/******************************************************************************* - * NAME : UnifiDebugKeepRadioOn - * PSID : 2545 (0x09F1) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Keep the radio on. For debug purposes only. Setting the value to FALSE - * means radio on/off functionality will behave normally. Note that setting - * this value to TRUE will automatically disable dorm. The intention is - * not* for this value to be changed at runtime. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEBUG_KEEP_RADIO_ON 0x09F1 - -/******************************************************************************* - * NAME : UnifiForceFixedDurationSchedule - * PSID : 2546 (0x09F2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : TU - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * For schedules with fixed duration e.g. scan, unsync VIF, the schedule - * will be forced after this time to avoid VIF starving - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FORCE_FIXED_DURATION_SCHEDULE 0x09F2 - -/******************************************************************************* - * NAME : UnifiRameUpdateMibs - * PSID : 2547 (0x09F3) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * When this mib is called/toggled MACRAME mibs will be read and compared - * with mib values in ramedata.mibs and updated if the value changes - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RAME_UPDATE_MIBS 0x09F3 - -/******************************************************************************* - * NAME : UnifiGoScanAbsenceDuration - * PSID : 2548 (0x09F4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : beacon intervals - * MIN : 0 - * MAX : 65535 - * DEFAULT : 7 - * DESCRIPTION : - * Duration of the Absence time to use when protecting P2PGO VIFs from scan - * operations. A value of 0 disables the feature. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_GO_SCAN_ABSENCE_DURATION 0x09F4 - -/******************************************************************************* - * NAME : UnifiGoScanAbsencePeriod - * PSID : 2549 (0x09F5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : beacon intervals - * MIN : 0 - * MAX : 65535 - * DEFAULT : 14 - * DESCRIPTION : - * Period of the Absence/Presence times cycles to use when protecting P2PGO - * VIFs from scan operations. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_GO_SCAN_ABSENCE_PERIOD 0x09F5 - -/******************************************************************************* - * NAME : UnifiMaxClient - * PSID : 2550 (0x09F6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 10 - * DEFAULT : 10 - * DESCRIPTION : - * Restricts the maximum number of associated STAs for SoftAP. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAX_CLIENT 0x09F6 - -/******************************************************************************* - * NAME : UnifiTdlsInP2pActivated - * PSID : 2556 (0x09FC) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enable TDLS in P2P. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_IN_P2P_ACTIVATED 0x09FC - -/******************************************************************************* - * NAME : UnifiTdlsActivated - * PSID : 2558 (0x09FE) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Enable TDLS. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_ACTIVATED 0x09FE - -/******************************************************************************* - * NAME : UnifiTdlsTpThresholdPktSecs - * PSID : 2559 (0x09FF) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 100 - * DESCRIPTION : - * Used for "throughput_threshold_pktsecs" of - * RAME-MLME-ENABLE-PEER-TRAFFIC-REPORTING.request. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_TP_THRESHOLD_PKT_SECS 0x09FF - -/******************************************************************************* - * NAME : UnifiTdlsRssiThreshold - * PSID : 2560 (0x0A00) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : -75 - * DESCRIPTION : - * FW initiated TDLS Discovery/Setup procedure. If the RSSI of a received - * TDLS Discovery Response frame is greater than this value, initiate the - * TDLS Setup procedure. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_RSSI_THRESHOLD 0x0A00 - -/******************************************************************************* - * NAME : UnifiTdlsMaximumRetry - * PSID : 2561 (0x0A01) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_MAXIMUM_RETRY 0x0A01 - -/******************************************************************************* - * NAME : UnifiTdlsTpMonitorSecs - * PSID : 2562 (0x0A02) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Measurement period for recording the number of packets sent to a peer - * over a TDLS link. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_TP_MONITOR_SECS 0x0A02 - -/******************************************************************************* - * NAME : UnifiTdlsBasicHtMcsSet - * PSID : 2563 (0x0A03) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_BASIC_HT_MCS_SET 0x0A03 - -/******************************************************************************* - * NAME : UnifiTdlsBasicVhtMcsSet - * PSID : 2564 (0x0A04) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_BASIC_VHT_MCS_SET 0x0A04 - -/******************************************************************************* - * NAME : Dot11TdlsDiscoveryRequestWindow - * PSID : 2565 (0x0A05) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 10 - * DESCRIPTION : - * Time to gate Discovery Request frame (in DTIM intervals) after - * transmitting a Discovery Request frame. - *******************************************************************************/ -#define SLSI_PSID_DOT11_TDLS_DISCOVERY_REQUEST_WINDOW 0x0A05 - -/******************************************************************************* - * NAME : Dot11TdlsResponseTimeout - * PSID : 2566 (0x0A06) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 5 - * DESCRIPTION : - * If a valid Setup Response frame is not received within (seconds), the - * initiator STA shall terminate the setup procedure and discard any Setup - * Response frames. - *******************************************************************************/ -#define SLSI_PSID_DOT11_TDLS_RESPONSE_TIMEOUT 0x0A06 - -/******************************************************************************* - * NAME : Dot11TdlsChannelSwitchActivated - * PSID : 2567 (0x0A07) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_DOT11_TDLS_CHANNEL_SWITCH_ACTIVATED 0x0A07 - -/******************************************************************************* - * NAME : UnifiTdlsDesignForTestMode - * PSID : 2568 (0x0A08) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_DESIGN_FOR_TEST_MODE 0x0A08 - -/******************************************************************************* - * NAME : UnifiTdlsWiderBandwidthProhibited - * PSID : 2569 (0x0A09) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Wider bandwidth prohibited flag. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_WIDER_BANDWIDTH_PROHIBITED 0x0A09 - -/******************************************************************************* - * NAME : UnifiTdlsKeyLifeTimeInterval - * PSID : 2577 (0x0A11) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X000FFFFF - * DESCRIPTION : - * Build the Key Lifetime Interval in the TDLS Setup Request frame. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_KEY_LIFE_TIME_INTERVAL 0x0A11 - -/******************************************************************************* - * NAME : UnifiTdlsTeardownFrameTxTimeout - * PSID : 2578 (0x0A12) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 500 - * DESCRIPTION : - * Allowed time in milliseconds for a Teardown frame to be transmitted. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TDLS_TEARDOWN_FRAME_TX_TIMEOUT 0x0A12 - -/******************************************************************************* - * NAME : UnifiWifiSharingEnabled - * PSID : 2580 (0x0A14) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables WiFi Sharing feature - *******************************************************************************/ -#define SLSI_PSID_UNIFI_WIFI_SHARING_ENABLED 0x0A14 - -/******************************************************************************* - * NAME : UnifiWiFiSharing5GHzChannel - * PSID : 2582 (0x0A16) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 8 - * MAX : 8 - * DEFAULT : { 0X00, 0XC0, 0XFF, 0XFF, 0X7F, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * Applicable 5GHz Primary Channels mask. Defined in a uint64 represented by - * the octet string. First byte of the octet string maps to LSB. Bits 0-13 - * representing 2.4G channels are always set to 0. Mapping defined in - * ChannelisationRules; i.e. Bit 14 maps to channel 36. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_WI_FI_SHARING5_GHZ_CHANNEL 0x0A16 - -/******************************************************************************* - * NAME : UnifiWifiSharingChannelSwitchCount - * PSID : 2583 (0x0A17) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 3 - * MAX : 10 - * DEFAULT : 10 - * DESCRIPTION : - * Channel switch announcement count which will be used in the Channel - * announcement IE when using wifi sharing - *******************************************************************************/ -#define SLSI_PSID_UNIFI_WIFI_SHARING_CHANNEL_SWITCH_COUNT 0x0A17 - -/******************************************************************************* - * NAME : UnifiChannelAnnouncementCount - * PSID : 2584 (0x0A18) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Channel switch announcement count which will be used in the Channel - * announcement IE - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CHANNEL_ANNOUNCEMENT_COUNT 0x0A18 - -/******************************************************************************* - * NAME : UnifiRaTestStoredSa - * PSID : 2585 (0x0A19) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X00000000 - * DESCRIPTION : - * Test only: Source address of router contained in virtural router - * advertisement packet, specified in chapter '6.2 Forward Received RA frame - * to Host' in SC-506393-TE - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RA_TEST_STORED_SA 0x0A19 - -/******************************************************************************* - * NAME : UnifiRaTestStoreFrame - * PSID : 2586 (0x0A1A) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X00000000 - * DESCRIPTION : - * Test only: Virtual router advertisement packet. Specified in chapter '6.2 - * Forward Received RA frame to Host' in SC-506393-TE - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RA_TEST_STORE_FRAME 0x0A1A - -/******************************************************************************* - * NAME : Dot11TdlsPeerUapsdBufferStaActivated - * PSID : 2587 (0x0A1B) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enable TDLS peer U-APSD. - *******************************************************************************/ -#define SLSI_PSID_DOT11_TDLS_PEER_UAPSD_BUFFER_STA_ACTIVATED 0x0A1B - -/******************************************************************************* - * NAME : UnifiProbeResponseLifetimeP2p - * PSID : 2600 (0x0A28) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 500 - * DESCRIPTION : - * Lifetime of proberesponse frame in unit of ms for P2P. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PROBE_RESPONSE_LIFETIME_P2P 0x0A28 - -/******************************************************************************* - * NAME : UnifiStaChannelSwitchSlowApActivated - * PSID : 2601 (0x0A29) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: ChanelSwitch: - * Enable waiting for a slow AP. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STA_CHANNEL_SWITCH_SLOW_AP_ACTIVATED 0x0A29 - -/******************************************************************************* - * NAME : UnifiStaChannelSwitchSlowApMaxTime - * PSID : 2604 (0x0A2C) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 70 - * DESCRIPTION : - * ChannelSwitch delay for Slow APs. In Seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STA_CHANNEL_SWITCH_SLOW_AP_MAX_TIME 0x0A2C - -/******************************************************************************* - * NAME : UnifiStaChannelSwitchSlowApPollInterval - * PSID : 2605 (0x0A2D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1 - * DESCRIPTION : - * ChannelSwitch polling interval for Slow APs. In Seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STA_CHANNEL_SWITCH_SLOW_AP_POLL_INTERVAL 0x0A2D - -/******************************************************************************* - * NAME : UnifiStaChannelSwitchSlowApProcedureTimeoutIncrement - * PSID : 2606 (0x0A2E) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * ChannelSwitch procedure timeout increment for Slow APs. In Seconds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STA_CHANNEL_SWITCH_SLOW_AP_PROCEDURE_TIMEOUT_INCREMENT 0x0A2E - -/******************************************************************************* - * NAME : UnifiMlmeScanMaxAerials - * PSID : 2607 (0x0A2F) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 65535 - * DEFAULT : 1 - * DESCRIPTION : - * Limit the number of Aerials that Scan will use. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_MAX_AERIALS 0x0A2F - -/******************************************************************************* - * NAME : UnifiApfEnabled - * PSID : 2650 (0x0A5A) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * It is used to enable or disable Android Packet Filter(APF). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_APF_ENABLED 0x0A5A - -/******************************************************************************* - * NAME : UnifiApfVersion - * PSID : 2651 (0x0A5B) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 4 - * DESCRIPTION : - * APF version currently supported by the FW. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_APF_VERSION 0x0A5B - -/******************************************************************************* - * NAME : UnifiApfMaxSize - * PSID : 2652 (0x0A5C) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 2048 - * DEFAULT : 1024 - * DESCRIPTION : - * Max size in bytes supported by FW per VIF. Includes both program len and - * data len. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_APF_MAX_SIZE 0x0A5C - -/******************************************************************************* - * NAME : UnifiApfActiveMode - * PSID : 2653 (0x0A5D) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1 - * DESCRIPTION : - * Indicates if APF is supported in host active mode. Applicable to only - * group addressed frames. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_APF_ACTIVE_MODE 0x0A5D - -/******************************************************************************* - * NAME : UnifiCsrOnlyMibShield - * PSID : 4001 (0x0FA1) - * PER INTERFACE?: NO - * TYPE : unifiCSROnlyMIBShield - * MIN : 0 - * MAX : 255 - * DEFAULT : 2 - * DESCRIPTION : - * Each element of the MIB has a set of read/write access constraints that - * may be applied when the element is accessed by the host. For most - * elements the constants are derived from their MAX-ACCESS clauses. - * unifiCSROnlyMIBShield controls the access mechanism. If this entry is set - * to 'warn', when the host makes an inappropriate access to a MIB - * variable (e.g., writing to a 'read-only' entry) then the - * firmware attempts to send a warning message to the host, but access is - * allowed to the MIB variable. If this entry is set to 'guard' - * then inappropriate accesses from the host are prevented. If this entry is - * set to 'alarm' then inappropriate accesses from the host are - * prevented and the firmware attempts to send warning messages to the host. - * If this entry is set to 'open' then no access constraints are - * applied and now warnings issued. Note that certain MIB entries have - * further protection schemes. In particular, the MIB prevents the host from - * reading some security keys (WEP keys, etc.). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CSR_ONLY_MIB_SHIELD 0x0FA1 - -/******************************************************************************* - * NAME : UnifiPrivateBbbTxFilterConfig - * PSID : 4071 (0x0FE7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X17 - * DESCRIPTION : - * entry is written directly to the BBB_TX_FILTER_CONFIG register. Only the - * lower eight bits of this register are implemented . Bits 0-3 are the - * 'Tx Gain', bits 6-8 are the 'Tx Delay'. This register - * should only be changed by an expert. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PRIVATE_BBB_TX_FILTER_CONFIG 0x0FE7 - -/******************************************************************************* - * NAME : UnifiPrivateSwagcFrontEndGain - * PSID : 4075 (0x0FEB) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : - * DESCRIPTION : - * Gain of the path between chip and antenna when LNA is on. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PRIVATE_SWAGC_FRONT_END_GAIN 0x0FEB - -/******************************************************************************* - * NAME : UnifiPrivateSwagcFrontEndLoss - * PSID : 4076 (0x0FEC) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : - * DESCRIPTION : - * Loss of the path between chip and antenna when LNA is off. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PRIVATE_SWAGC_FRONT_END_LOSS 0x0FEC - -/******************************************************************************* - * NAME : UnifiPrivateSwagcExtThresh - * PSID : 4077 (0x0FED) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : -25 - * DESCRIPTION : - * Signal level at which external LNA will be used for AGC purposes. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PRIVATE_SWAGC_EXT_THRESH 0x0FED - -/******************************************************************************* - * NAME : UnifiCsrOnlyPowerCalDelay - * PSID : 4078 (0x0FEE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : microseconds - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Delay applied at each step of the power calibration routine used with an - * external PA. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CSR_ONLY_POWER_CAL_DELAY 0x0FEE - -/******************************************************************************* - * NAME : UnifiRxAgcControl - * PSID : 4079 (0x0FEF) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 9 - * MAX : 11 - * DEFAULT : - * DESCRIPTION : - * Override the AGC by adjusting the Rx minimum and maximum gains of each - * stage. Set requests write the values to a static structure in - * mac/hal/halradio/halradio_agc.c. The saved values are written to the Jar - * register WLRF_RADIO_AGC_CONFIG2 and to the Night registers - * WL_RADIO_AGC_CONFIG2 and WL_RADIO_AGC_CONFIG3. The saved values are also - * used to configure the AGC whenever halradio_agc_setup() is called. Get - * requests read the values from the static structure in - * mac/hal/halradio/halradio_agc.c. AGC enables are not altered. Fixed gain - * may be tested by setting the minimums and maximums to the same value. - * Version. octet 0 - Version number for this mib. Gain values. Default in - * brackets. octet 1 - 5G LNA minimum gain (0). octet 2 - 5G LNA maximum - * gain (4). octet 3 - 2G LNA minimum gain (0). octet 4 - 2G LNA maximum - * gain (5). octet 5 - Mixer minimum gain (0). octet 6 - Mixer maximum gain - * (2). octet 7 - ABB minimum gain (0). octet 8 - ABB maximum gain (27). - * octet 9 - Digital minimum gain (0). octet 10 - Digital maximum gain (7). - * For Rock / Hopper the saved values are written to the Hopper register - * WLRF_RADIO_AGC_CONFIG2_I0, WLRF_RADIO_AGC_CONFIG2_I1 and Rock registers - * WL_RADIO_AGC_CONFIG3_I0, WL_RADIO_AGC_CONFIG3_I1 Version. octet 0 - - * Version number for this mib. Gain values. Default in brackets. octet 1 - - * 5G FE minimum gain (1). octet 2 - 5G FE maximum gain (8). octet 3 - 2G FE - * minimum gain (0). octet 4 - 2G FE maximum gain (8). octet 5 - ABB minimum - * gain (0). octet 6 - ABB maximum gain (8). octet 7 - Digital minimum gain - * (0). octet 8 - Digital maximum gain (17). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_AGC_CONTROL 0x0FEF - -/******************************************************************************* - * NAME : UnifiWapiQosMask - * PSID : 4130 (0x1022) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 15 - * DESCRIPTION : - * Forces the WAPI encryption hardware use the QoS mask specified.This mib - * value will be updated if "unifiRameUpdateMibs" mib is toggled - *******************************************************************************/ -#define SLSI_PSID_UNIFI_WAPI_QOS_MASK 0x1022 - -/******************************************************************************* - * NAME : UnifiWmmStallEnable - * PSID : 4139 (0x102B) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1 - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Enable - * workaround stall WMM traffic if the admitted time has been used up, used - * for certtification. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_WMM_STALL_ENABLE 0x102B - -/******************************************************************************* - * NAME : UnifiRaaTxHostRate - * PSID : 4148 (0x1034) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 16385 - * DESCRIPTION : - * Fixed TX rate set by Host. Ideally this should be done by the driver. 0 - * means "host did not specified any rate". - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RAA_TX_HOST_RATE 0x1034 - -/******************************************************************************* - * NAME : UnifiFallbackShortFrameRetryDistribution - * PSID : 4149 (0x1035) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 6 - * MAX : 5 - * DEFAULT : {0X3, 0X2, 0X2, 0X2, 0X1, 0X0} - * DESCRIPTION : - * Configure the retry distribution for fallback for short frames octet 0 - - * Number of retries for starting rate. octet 1 - Number of retries for next - * rate. octet 2 - Number of retries for next rate. octet 3 - Number of - * retries for next rate. octet 4 - Number of retries for next rate. octet 5 - * - Number of retries for last rate. If 0 is written to an entry then the - * retries for that rate will be the short retry limit minus the sum of the - * retries for each rate above that entry (e.g. 15 - 5). Therefore, this - * should always be the value for octet 4. Also, when the starting rate has - * short guard enabled, the number of retries in octet 1 will be used and - * for the next rate in the fallback table (same MCS value, but with sgi - * disabled) octet 0 number of retries will be used. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FALLBACK_SHORT_FRAME_RETRY_DISTRIBUTION 0x1035 - -/******************************************************************************* - * NAME : UnifiRxthroughputlow - * PSID : 4150 (0x1036) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 37500000 - * DESCRIPTION : - * Lower threshold for number of bytes received in a second - default value - * based on 300Mbps - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RXTHROUGHPUTLOW 0x1036 - -/******************************************************************************* - * NAME : UnifiRxthroughputhigh - * PSID : 4151 (0x1037) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 50000000 - * DESCRIPTION : - * Upper threshold for number of bytes received in a second - default value - * based on 400Mbps - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RXTHROUGHPUTHIGH 0x1037 - -/******************************************************************************* - * NAME : UnifiSetFixedAmpduAggregationSize - * PSID : 4152 (0x1038) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * A non 0 value defines the max number of mpdus that a ampdu can have. A 0 - * value tells FW to manage the aggregation size. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SET_FIXED_AMPDU_AGGREGATION_SIZE 0x1038 - -/******************************************************************************* - * NAME : UnifiThroughputDebugReportInterval - * PSID : 4153 (0x1039) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1000 - * DESCRIPTION : - * dataplane reports throughput diag report every this interval in msec. 0 - * means to disable this report. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_THROUGHPUT_DEBUG_REPORT_INTERVAL 0x1039 - -/******************************************************************************* - * NAME : UnifiPreEbrtWindow - * PSID : 4171 (0x104B) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : microseconds - * MIN : 0 - * MAX : 2147483647 - * DEFAULT : 100 - * DESCRIPTION : - * Latest time before the expected beacon reception time that UniFi will - * turn on its radio in order to receive the beacon. Reducing this value can - * reduce UniFi power consumption when using low power modes, however a - * value which is too small may cause beacons to be missed, requiring the - * radio to remain on for longer periods to ensure reception of the - * subsequent beacon. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PRE_EBRT_WINDOW 0x104B - -/******************************************************************************* - * NAME : UnifiPostEbrtWindow - * PSID : 4173 (0x104D) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : microseconds - * MIN : 0 - * MAX : 2147483647 - * DEFAULT : 2000 - * DESCRIPTION : - * Minimum time after the expected beacon reception time that UniFi will - * continue to listen for the beacon in an infrastructure BSS before timing - * out. Reducing this value can reduce UniFi power consumption when using - * low power modes, however a value which is too small may cause beacons to - * be missed, requiring the radio to remain on for longer periods to ensure - * reception of the subsequent beacon. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_POST_EBRT_WINDOW 0x104D - -/******************************************************************************* - * NAME : UnifiPsPollThreshold - * PSID : 4179 (0x1053) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 30 - * DESCRIPTION : - * PS Poll threshold. When Unifi chip is configured for normal power save - * mode and when access point does not respond to PS-Poll requests, then a - * fault will be generated on non-zero PS Poll threshold indicating mode has - * been switched from power save to fast power save. Ignored PS Poll count - * is given as the fault argument. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PS_POLL_THRESHOLD 0x1053 - -/******************************************************************************* - * NAME : UnifiSableContainerSizeConfiguration - * PSID : 5000 (0x1388) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 3 - * MAX : 3 - * DEFAULT : {0X64} - * DESCRIPTION : - * Sable Container Size Configuration Sable WLAN reserved memory size is - * determined by the host. Sable TLV containers are allocated from this WLAN - * reserved area. Each container has different requirement on its size. For - * example, frame logging or IQ capture would be very greedy, requesting - * most of available memroy. But some just need fixed size, but not large. - * To cope with such requirements, each container size is configured with - * the following rules: 1. To allocate a certain percentage of the whole - * wlan reserved area, put the percentage in hex format. For example, - * 0x28(=40) means 40% of reserved area will be assigned. The number - * 0x64(=100) is specially treated that all remaining space will be assigned - * after all the other containers are first served. 2. To request (n * 2048) - * bytes, put (100 + n) value in hex format. For example, 0x96 (= 150) means - * 50 * 2048 = 102400 bytes. Here are the list of containers: - octet 0 - - * WTLV_CONTAINER_ID_DPLANE_FRAME_LOG - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SABLE_CONTAINER_SIZE_CONFIGURATION 0x1388 - -/******************************************************************************* - * NAME : UnifiSableFrameLogMode - * PSID : 5001 (0x1389) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 2 - * DEFAULT : 2 - * DESCRIPTION : - * Sable Frame Logging mode - 0: disable frame logging - 1: enable frame - * logging always, regardless of CPU resource state - 2: dynamically enable - * frame logging base on CPU resource. If CPU too busy, frame logging is - * disabled. Logging is enabled when CPU resource gets recovered. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SABLE_FRAME_LOG_MODE 0x1389 - -/******************************************************************************* - * NAME : UnifiSableFrameLogCpuThresPercent - * PSID : 5002 (0x138A) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 95 - * DESCRIPTION : - * CPU target in percent. When CPU usage is higher than this target, frame - * logging will be disabled by firmware. Firmware will check if CPU resource - * is recovered every 1 second. If CPU resource recovered, then frame - * logging is re-enabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SABLE_FRAME_LOG_CPU_THRES_PERCENT 0x138A - -/******************************************************************************* - * NAME : UnifiSableFrameLogCpuOverheadPercent - * PSID : 5003 (0x138B) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 3 - * DESCRIPTION : - * Expected CPU overhead introduced by frame logging. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SABLE_FRAME_LOG_CPU_OVERHEAD_PERCENT 0x138B - -/******************************************************************************* - * NAME : UnifiDebugSvcModeStackHighWaterMark - * PSID : 5010 (0x1392) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Read the SVC mode stack high water mark in bytes - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEBUG_SVC_MODE_STACK_HIGH_WATER_MARK 0x1392 - -/******************************************************************************* - * NAME : UnifiOverrideEdcaParamBe - * PSID : 5023 (0x139F) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 4 - * MAX : 4 - * DEFAULT : { 0X03, 0XA4, 0X00, 0X00 } - * DESCRIPTION : - * Override the BE EDCA parameters. octet 0 - AIFS octet 1 - [7:4] ECW MAX - * [3:0] ECW MIN octet 2 ~ 3 - TXOP[7:0] TXOP[15:8] in 32 usec units for - * both non-HT and HT connections. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_EDCA_PARAM_BE 0x139F - -/******************************************************************************* - * NAME : UnifiOverrideEdcaParamBeEnable - * PSID : 5024 (0x13A0) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * override STA - BE EDCA using the values in unifiOverrideEDCAParamBE for - * certification. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OVERRIDE_EDCA_PARAM_BE_ENABLE 0x13A0 - -/******************************************************************************* - * NAME : UnifiPanicSubSystemControl - * PSID : 5026 (0x13A2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * PANIC levels for WLAN SubSystems. Panic level is used to filter Panic - * sent to the host. 4 levels of Panic per subsystem are available - * (FAILURE_LEVEL_T): a. 0 FATAL - Always reported to host b. 1 ERROR c. 2 - * WARNING d. 3 DEBUG NOTE: If Panic level of a subsystem is configured to - * FATAL, all the Panics within that subsystem configured to FATAL will be - * effective, panics with ERROR, WARNING and Debug level will be converted - * to faults. If Panic level of a subsystem is configured to WARNING, all - * the panics within that subsystem configured to FATAL, ERROR and WARNING - * will be issued to host, panics with Debug level will be converted to - * faults. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PANIC_SUB_SYSTEM_CONTROL 0x13A2 - -/******************************************************************************* - * NAME : UnifiFaultEnable - * PSID : 5027 (0x13A3) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Send Fault to host state. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FAULT_ENABLE 0x13A3 - -/******************************************************************************* - * NAME : UnifiFaultSubSystemControl - * PSID : 5028 (0x13A4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Fault levels for WLAN SubSystems. Fault level is used to filter faults - * sent to the host. 4 levels of faults per subsystem are available - * (FAILURE_LEVEL_T): a. 0 ERROR b. 1 WARNING c. 2 INFO_1 d. 3 INFO_2 - * Modifying Fault Levels at run time: 1. Set the fault level for the - * subsystems in unifiFaultConfigTable 2. Set unifiFaultEnable NOTE: If - * fault level of a subsystem is configured to ERROR, all the faults within - * that subsystem configured to ERROR will only be issued to host, faults - * with WARNING, INFO_1 and INFO_2 level will be converted to debug message - * If fault level of a subsystem is configured to WARNING, all the faults - * within that subsystem configured to ERROR and WARNING will be issued to - * host, faults with INFO_1 and INFO_2 level will be converted to debug - * message - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FAULT_SUB_SYSTEM_CONTROL 0x13A4 - -/******************************************************************************* - * NAME : UnifiDebugModuleControl - * PSID : 5029 (0x13A5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Debug Module levels for all modules. Module debug level is used to filter - * debug messages sent to the host. Only 6 levels of debug per module are - * available: a. -1 No debug created. b. 0 Debug if compiled in. Should not - * cause Buffer Full in normal testing. c. 1 - 3 Levels to allow sensible - * setting of the .hcf file while running specific tests or debugging d. 4 - * Debug will harm normal execution due to excessive levels or processing - * time required. Only used in emergency debugging. Additional control for - * FSM transition and FSM signals logging is provided. Debug module level - * and 2 boolean flags are encoded within a uint16: Function | Is sending - * FSM signals | Is sending FSM transitions | Is sending FSM Timers | - * Reserved | Module level (signed int) - * -_-_-_-_-_+-_-_-_-_-_-_-_-_-_-_-_-_-_+-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_+-_-_-_-_-_-_-_-_-_-_-_-_-_+-_-_-_-_-_-_+-_-_-_-_-_-_-_-_-_-_-_-_-_- Bits | 15 | 14 | 13 | 12 - 8 | 7 - 0 Note: 0x00FF disables any debug for a module 0xE004 enables all debug for a module - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEBUG_MODULE_CONTROL 0x13A5 - -/******************************************************************************* - * NAME : UnifiTxUsingLdpcEnabled - * PSID : 5030 (0x13A6) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * LDPC will be used to code packets, for transmit only. If disabled, chip - * will not send LDPC coded packets even if peer supports it. To advertise - * reception of LDPC coded packets,enable bit 0 of unifiHtCapabilities, and - * bit 4 of unifiVhtCapabilities. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_USING_LDPC_ENABLED 0x13A6 - -/******************************************************************************* - * NAME : UnifiTxSettings - * PSID : 5031 (0x13A7) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter settings - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_SETTINGS 0x13A7 - -/******************************************************************************* - * NAME : UnifiTxGainSettings - * PSID : 5032 (0x13A8) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter gain settings - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_GAIN_SETTINGS 0x13A8 - -/******************************************************************************* - * NAME : UnifiTxAntennaConnectionLossFrequency - * PSID : 5033 (0x13A9) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 3940 - * MAX : 12000 - * DEFAULT : - * DESCRIPTION : - * The corresponding set of frequency values for - * TxAntennaConnectionLossTable - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_ANTENNA_CONNECTION_LOSS_FREQUENCY 0x13A9 - -/******************************************************************************* - * NAME : UnifiTxAntennaConnectionLoss - * PSID : 5034 (0x13AA) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : - * DESCRIPTION : - * The set of Antenna Connection Loss value (qdB), which is used for - * TPO/EIRP conversion - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_ANTENNA_CONNECTION_LOSS 0x13AA - -/******************************************************************************* - * NAME : UnifiTxAntennaMaxGainFrequency - * PSID : 5035 (0x13AB) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 3940 - * MAX : 12000 - * DEFAULT : - * DESCRIPTION : - * The corresponding set of frequency values for TxAntennaMaxGain - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_ANTENNA_MAX_GAIN_FREQUENCY 0x13AB - -/******************************************************************************* - * NAME : UnifiTxAntennaMaxGain - * PSID : 5036 (0x13AC) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : - * DESCRIPTION : - * The set of Antenna Max Gain value (qdB), which is used for TPO/EIRP - * conversion - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_ANTENNA_MAX_GAIN 0x13AC - -/******************************************************************************* - * NAME : UnifiRxExternalGainFrequency - * PSID : 5037 (0x13AD) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 3940 - * MAX : 12000 - * DEFAULT : - * DESCRIPTION : - * The set of RSSI offset value - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_EXTERNAL_GAIN_FREQUENCY 0x13AD - -/******************************************************************************* - * NAME : UnifiRxExternalGain - * PSID : 5038 (0x13AE) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : - * DESCRIPTION : - * The table giving frequency-dependent RSSI offset value - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_EXTERNAL_GAIN 0x13AE - -/******************************************************************************* - * NAME : UnifiTxSgI20Enabled - * PSID : 5040 (0x13B0) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * SGI 20MHz will be used to code packets for transmit only. If disabled, - * chip will not send SGI 20MHz packets even if peer supports it. To - * advertise reception of SGI 20MHz packets, enable bit 5 of - * unifiHtCapabilities. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_SG_I20_ENABLED 0x13B0 - -/******************************************************************************* - * NAME : UnifiTxSgI40Enabled - * PSID : 5041 (0x13B1) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * SGI 40MHz will be used to code packets, for transmit only. If disabled, - * chip will not send SGI 40MHz packets even if peer supports it. To - * advertise reception of SGI 40MHz packets, enable bit 6 of - * unifiHtCapabilities. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_SG_I40_ENABLED 0x13B1 - -/******************************************************************************* - * NAME : UnifiTxSgI80Enabled - * PSID : 5042 (0x13B2) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * SGI 80MHz will be used to code packets, for transmit only. If disabled, - * chip will not send SGI 80MHz packets even if peer supports it. To - * advertise reception of SGI 80MHz packets, enable bit 5 of - * unifiVhtCapabilities. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_SG_I80_ENABLED 0x13B2 - -/******************************************************************************* - * NAME : UnifiTxSgI160Enabled - * PSID : 5043 (0x13B3) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * SGI 160/80+80MHz will be used to code packets, for transmit only. If - * disabled, chip will not send SGI 160/80+80MHz packets even if peer - * supports it. To advertise reception of SGI 160/80+80MHz packets, enable - * bit 6 of unifiVhtCapabilities. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_SG_I160_ENABLED 0x13B3 - -/******************************************************************************* - * NAME : UnifiMacAddressRandomisation - * PSID : 5044 (0x13B4) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Golden Certification MIB don't delete, change PSID or name: Enabling Mac - * Address Randomisation to be applied for Probe Requests when scanning. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAC_ADDRESS_RANDOMISATION 0x13B4 - -/******************************************************************************* - * NAME : UnifiMacAddressRandomisationMask - * PSID : 5047 (0x13B7) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 6 - * MAX : 6 - * DEFAULT : { 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * FW randomises MAC Address bits that have a corresponding bit set to 0 in - * the MAC Mask for Probe Requests. This excludes U/L and I/G bits which - * will be set to Local and Individual respectively. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAC_ADDRESS_RANDOMISATION_MASK 0x13B7 - -/******************************************************************************* - * NAME : UnifiWipsActivated - * PSID : 5050 (0x13BA) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables Wips. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_WIPS_ACTIVATED 0x13BA - -/******************************************************************************* - * NAME : UnifiRfTestModeEnabled - * PSID : 5054 (0x13BE) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Test only: Set to true when running in RF Test mode. Setting this MIB key - * to true prevents setting mandatory HT MCS Rates. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RF_TEST_MODE_ENABLED 0x13BE - -/******************************************************************************* - * NAME : UnifiTxPowerDetectorResponse - * PSID : 5055 (0x13BF) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter detector response settings. 2G settings - * before 5G. Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_POWER_DETECTOR_RESPONSE 0x13BF - -/******************************************************************************* - * NAME : UnifiTxDetectorTemperatureCompensation - * PSID : 5056 (0x13C0) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter detector temperature compensation settings. - * 2G settings before 5G. Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_DETECTOR_TEMPERATURE_COMPENSATION 0x13C0 - -/******************************************************************************* - * NAME : UnifiTxDetectorFrequencyCompensation - * PSID : 5057 (0x13C1) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter detector frequency compensation settings. - * 2G settings before 5G. Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_DETECTOR_FREQUENCY_COMPENSATION 0x13C1 - -/******************************************************************************* - * NAME : UnifiTxOpenLoopTemperatureCompensation - * PSID : 5058 (0x13C2) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter open-loop temperature compensation - * settings. 2G settings before 5G. Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_OPEN_LOOP_TEMPERATURE_COMPENSATION 0x13C2 - -/******************************************************************************* - * NAME : UnifiTxOpenLoopFrequencyCompensation - * PSID : 5059 (0x13C3) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter open-loop frequency compensation settings. - * 2G settings before 5G. Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_OPEN_LOOP_FREQUENCY_COMPENSATION 0x13C3 - -/******************************************************************************* - * NAME : UnifiTxOfdmSelect - * PSID : 5060 (0x13C4) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 4 - * MAX : 8 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter OFDM selection settings - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_OFDM_SELECT 0x13C4 - -/******************************************************************************* - * NAME : UnifiTxDigGain - * PSID : 5061 (0x13C5) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 16 - * MAX : 48 - * DEFAULT : - * DESCRIPTION : - * Specify gain specific modulation power optimisation. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_DIG_GAIN 0x13C5 - -/******************************************************************************* - * NAME : UnifiChipTemperature - * PSID : 5062 (0x13C6) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : celcius - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Read the chip temperature as seen by WLAN radio firmware. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CHIP_TEMPERATURE 0x13C6 - -/******************************************************************************* - * NAME : UnifiBatteryVoltage - * PSID : 5063 (0x13C7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * UNITS : millivolt - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Battery voltage - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BATTERY_VOLTAGE 0x13C7 - -/******************************************************************************* - * NAME : UnifiTxOobConstraints - * PSID : 5064 (0x13C8) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * OOB constraints table. | octects | description | - * |-_-_-_-_-+-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-| | 0 | DPD applicability bitmask: 0 = no DPD, 1 = dynamic DPD, 2 = static DPD, 3 = applies to both static and dynamic DPD | | 1-2 | Bitmask indicating which regulatory domains this rule applies to FCC=bit0, ETSI=bit1, JAPAN=bit2 | | 3-4 | Bitmask indicating which band edges this rule applies to RICE_BAND_EDGE_ISM_24G_LOWER = bit 0, RICE_BAND_EDGE_ISM_24G_UPPER = bit 1, RICE_BAND_EDGE_U_NII_1_LOWER = bit 2, RICE_BAND_EDGE_U_NII_1_UPPER = bit 3, RICE_BAND_EDGE_U_NII_2_LOWER = bit 4, RICE_BAND_EDGE_U_NII_2_UPPER = bit 5, RICE_BAND_EDGE_U_NII_2E_LOWER = bit 6, RICE_BAND_EDGE_U_NII_2E_UPPER = bit 7, RICE_BAND_EDGE_U_NII_3_LOWER = bit 8, RICE_BAND_EDGE_U_NII_3_UPPER = bit 9 | | 5 | Bitmask indicating which modulation types this rule applies to (LSB/b0=DSSS/CCK, b1= OFDM0 modulation group, b2= OFDM1 modulation group) | | 6 | Bitmask indicating which channel bandwidths this rule applies to (LSB/b0=20MHz, b1=40MHz, b2=80MHz) | | 7 | Minimum distance to nearest band edge in 500 kHz units for which this constraint becomes is applicable. | | 8 | Maximum power (EIRP) for this particular constraint - specified in units of quarter dBm. | | 9-32 | Spectral shaping configuration to be used for this particular constraint. The value is specific to the radio hardware and should only be altered under advice from the IC supplier. | | 33-56| Tx DPD Spectral shaping configuration to be used for this particular constraint. The value is specific to the radio hardware and should only be altered under advice from the IC supplier. | | - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_OOB_CONSTRAINTS 0x13C8 - -/******************************************************************************* - * NAME : UnifiTxPaGainDpdTemperatureCompensation - * PSID : 5066 (0x13CA) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter PA gain for DPD temperature compensation - * settings. 2G settings before 5G. Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_PA_GAIN_DPD_TEMPERATURE_COMPENSATION 0x13CA - -/******************************************************************************* - * NAME : UnifiTxPaGainDpdFrequencyCompensation - * PSID : 5067 (0x13CB) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter PA gain for DPD frequency compensation - * settings. 2G settings before 5G. Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_PA_GAIN_DPD_FREQUENCY_COMPENSATION 0x13CB - -/******************************************************************************* - * NAME : UnifiTxPowerTrimConfig - * PSID : 5072 (0x13D0) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 25 - * MAX : 25 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter power trim settings - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_POWER_TRIM_CONFIG 0x13D0 - -/******************************************************************************* - * NAME : UnifiForceShortSlotTime - * PSID : 5080 (0x13D8) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * If set to true, forces FW to use short slot times for all VIFs. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FORCE_SHORT_SLOT_TIME 0x13D8 - -/******************************************************************************* - * NAME : UnifiTxGainStepSettings - * PSID : 5081 (0x13D9) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * Hardware specific transmitter gain step settings. 2G settings before 5G. - * Increasing order within band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TX_GAIN_STEP_SETTINGS 0x13D9 - -/******************************************************************************* - * NAME : UnifiDebugDisableRadioNannyActions - * PSID : 5082 (0x13DA) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Bitmap to disable the radio nanny actions. B0==radio 0, B1==radio 1 - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEBUG_DISABLE_RADIO_NANNY_ACTIONS 0x13DA - -/******************************************************************************* - * NAME : UnifiRxCckModemSensitivity - * PSID : 5083 (0x13DB) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 6 - * MAX : 6 - * DEFAULT : - * DESCRIPTION : - * Specify values of CCK modem sensitivity for scan, normal and low - * sensitivity. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_CCK_MODEM_SENSITIVITY 0x13DB - -/******************************************************************************* - * NAME : UnifiDpdPerBandwidth - * PSID : 5084 (0x13DC) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 63 - * DESCRIPTION : - * Bitmask to enable Digital Pre-Distortion per bandwidth - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPD_PER_BANDWIDTH 0x13DC - -/******************************************************************************* - * NAME : UnifiBbVersion - * PSID : 5085 (0x13DD) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Baseband chip version number determined by reading BBIC version - *******************************************************************************/ -#define SLSI_PSID_UNIFI_BB_VERSION 0x13DD - -/******************************************************************************* - * NAME : UnifiRfVersion - * PSID : 5086 (0x13DE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * RF chip version number determined by reading RFIC version - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RF_VERSION 0x13DE - -/******************************************************************************* - * NAME : UnifiReadHardwareCounter - * PSID : 5087 (0x13DF) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Read a value from a hardware packet counter for a specific radio_id and - * return it. The firmware will convert the radio_id to the associated - * mac_instance. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_READ_HARDWARE_COUNTER 0x13DF - -/******************************************************************************* - * NAME : UnifiClearRadioTrimCache - * PSID : 5088 (0x13E0) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Clears the radio trim cache. The parameter is ignored. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CLEAR_RADIO_TRIM_CACHE 0x13E0 - -/******************************************************************************* - * NAME : UnifiRadioTxSettingsRead - * PSID : 5089 (0x13E1) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Read value from Tx settings. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_TX_SETTINGS_READ 0x13E1 - -/******************************************************************************* - * NAME : UnifiModemSgiOffset - * PSID : 5090 (0x13E2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Overwrite SGI sampling offset. Indexed by Band and Bandwidth. Defaults - * currently defined in fw. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MODEM_SGI_OFFSET 0x13E2 - -/******************************************************************************* - * NAME : UnifiRadioTxPowerOverride - * PSID : 5091 (0x13E3) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -128 - * MAX : 127 - * DEFAULT : - * DESCRIPTION : - * Option in radio code to override the power requested by the upper layer - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_TX_POWER_OVERRIDE 0x13E3 - -/******************************************************************************* - * NAME : UnifiRxRadioCsMode - * PSID : 5092 (0x13E4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * OBSOLETE. Configures RX Radio CS detection for 80MHz bandwidth. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_RADIO_CS_MODE 0x13E4 - -/******************************************************************************* - * NAME : UnifiRxPriEnergyDetThreshold - * PSID : 5093 (0x13E5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * OBSOLETE. Energy detection threshold for primary 20MHz channel. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_PRI_ENERGY_DET_THRESHOLD 0x13E5 - -/******************************************************************************* - * NAME : UnifiRxSecEnergyDetThreshold - * PSID : 5094 (0x13E6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * OBSOLETE. Energy detection threshold for secondary 20MHz channel. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_SEC_ENERGY_DET_THRESHOLD 0x13E6 - -/******************************************************************************* - * NAME : UnifiAgcThresholds - * PSID : 5095 (0x13E7) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * AGC Thresholds settings - *******************************************************************************/ -#define SLSI_PSID_UNIFI_AGC_THRESHOLDS 0x13E7 - -/******************************************************************************* - * NAME : UnifiRadioRxSettingsRead - * PSID : 5096 (0x13E8) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Read value from Rx settings. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_RX_SETTINGS_READ 0x13E8 - -/******************************************************************************* - * NAME : UnifiStaticDpdGain - * PSID : 5097 (0x13E9) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 11 - * MAX : 27 - * DEFAULT : - * DESCRIPTION : - * Specify modulation specifc gains for static dpd optimisation. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_STATIC_DPD_GAIN 0x13E9 - -/******************************************************************************* - * NAME : UnifiIqBufferSize - * PSID : 5098 (0x13EA) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Buffer Size for IQ capture to allow CATs to read it. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_IQ_BUFFER_SIZE 0x13EA - -/******************************************************************************* - * NAME : UnifiNarrowbandCcaThresholds - * PSID : 5099 (0x13EB) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 255 - * DEFAULT : - * DESCRIPTION : - * The narrowband CCA ED thresholds so that the CCA-ED triggers at the - * regulatory value of -62 dBm. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NARROWBAND_CCA_THRESHOLDS 0x13EB - -/******************************************************************************* - * NAME : UnifiRadioCcaDebug - * PSID : 5100 (0x13EC) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Read values from Radio CCA settings. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_CCA_DEBUG 0x13EC - -/******************************************************************************* - * NAME : UnifiCcacsThresh - * PSID : 5101 (0x13ED) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Configures CCA CS thresholds. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CCACS_THRESH 0x13ED - -/******************************************************************************* - * NAME : UnifiCcaMasterSwitch - * PSID : 5102 (0x13EE) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X00540050 - * DESCRIPTION : - * Enables CCA - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CCA_MASTER_SWITCH 0x13EE - -/******************************************************************************* - * NAME : UnifiRxSyncCcaCfg - * PSID : 5103 (0x13EF) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Configures CCA per 20 MHz sub-band. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RX_SYNC_CCA_CFG 0x13EF - -/******************************************************************************* - * NAME : UnifiMacCcaBusyTime - * PSID : 5104 (0x13F0) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Counts the time CCA indicates busy - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAC_CCA_BUSY_TIME 0x13F0 - -/******************************************************************************* - * NAME : UnifiMacSecChanClearTime - * PSID : 5105 (0x13F1) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Configures PIFS - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MAC_SEC_CHAN_CLEAR_TIME 0x13F1 - -/******************************************************************************* - * NAME : UnifiDpdDebug - * PSID : 5106 (0x13F2) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Debug MIBs for DPD - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPD_DEBUG 0x13F2 - -/******************************************************************************* - * NAME : UnifiNarrowbandCcaDebug - * PSID : 5107 (0x13F3) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Read values from Radio CCA settings. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NARROWBAND_CCA_DEBUG 0x13F3 - -/******************************************************************************* - * NAME : UnifiNannyTemperatureReportDelta - * PSID : 5109 (0x13F5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 4 - * DESCRIPTION : - * A temperature difference, in degrees Celsius, above which the nanny - * process will generate a temperature update debug word - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NANNY_TEMPERATURE_REPORT_DELTA 0x13F5 - -/******************************************************************************* - * NAME : UnifiNannyTemperatureReportInterval - * PSID : 5110 (0x13F6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 200 - * DESCRIPTION : - * A report interval in milliseconds where temperature is checked - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NANNY_TEMPERATURE_REPORT_INTERVAL 0x13F6 - -/******************************************************************************* - * NAME : UnifiRadioRxDcocDebugIqValue - * PSID : 5111 (0x13F7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * RX DCOC debug testing. Allows user to override LUT index IQ values in - * combination with unifiRadioRxDcocDebug. This MIB sets IQ value that all - * LUT index Is and Qs get set to. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_RX_DCOC_DEBUG_IQ_VALUE 0x13F7 - -/******************************************************************************* - * NAME : UnifiRadioRxDcocDebug - * PSID : 5112 (0x13F8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * RX DCOC debug testing. Allows user to override LUT index IQ values in - * combination with unifiRadioRxDcocDebugIqValue. This MIB enables the - * feature. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_RX_DCOC_DEBUG 0x13F8 - -/******************************************************************************* - * NAME : UnifiNannyRetrimDpdMod - * PSID : 5113 (0x13F9) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2 - * DESCRIPTION : - * Bitmap to selectively enable nanny retrim of DPD per modulation. - * B0==OFDM0, B1==OFDM1, B2==CCK - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NANNY_RETRIM_DPD_MOD 0x13F9 - -/******************************************************************************* - * NAME : UnifiDisableDpdSubIteration - * PSID : 5114 (0x13FA) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * For Engineering debug use only. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DISABLE_DPD_SUB_ITERATION 0x13FA - -/******************************************************************************* - * NAME : UnifiRttCapabilities - * PSID : 5300 (0x14B4) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 8 - * MAX : 8 - * DEFAULT : { 0X01, 0X01, 0X01, 0X01, 0X00, 0X07, 0X1C, 0X32 } - * DESCRIPTION : - * RTT capabilities of the chip. see SC-506960-SW. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RTT_CAPABILITIES 0x14B4 - -/******************************************************************************* - * NAME : UnifiFtmMinDeltaFrames - * PSID : 5301 (0x14B5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 255 - * DEFAULT : 5 - * DESCRIPTION : - * Default minimum time between consecutive FTM frames in units of 100 us. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_MIN_DELTA_FRAMES 0x14B5 - -/******************************************************************************* - * NAME : UnifiFtmPerBurst - * PSID : 5302 (0x14B6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 1 - * MAX : 31 - * DEFAULT : 4 - * DESCRIPTION : - * Requested FTM frames per burst. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_PER_BURST 0x14B6 - -/******************************************************************************* - * NAME : UnifiFtmBurstDuration - * PSID : 5303 (0x14B7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 2 - * MAX : 11 - * DEFAULT : 6 - * DESCRIPTION : - * indicates the duration of a burst instance, values 0, 1, 12-14 are - * reserved, [2..11], the burst duration is defined as (250 x 2)^(N-2), and - * 15 means "no preference". - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_BURST_DURATION 0x14B7 - -/******************************************************************************* - * NAME : UnifiFtmNumOfBurstsExponent - * PSID : 5304 (0x14B8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 14 - * DEFAULT : - * DESCRIPTION : - * The number of burst instances is 2^(Number of Bursts Exponent), value 15 - * means "no preference". - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_NUM_OF_BURSTS_EXPONENT 0x14B8 - -/******************************************************************************* - * NAME : UnifiFtmAsapModeEnabled - * PSID : 5305 (0x14B9) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enable support for ASAP mode in FTM - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_ASAP_MODE_ENABLED 0x14B9 - -/******************************************************************************* - * NAME : UnifiFtmResponderEnabled - * PSID : 5306 (0x14BA) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enable support for FTM Responder - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_RESPONDER_ENABLED 0x14BA - -/******************************************************************************* - * NAME : UnifiFtmDefaultSessionEstablishmentTimeout - * PSID : 5307 (0x14BB) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 10 - * MAX : 100 - * DEFAULT : 50 - * DESCRIPTION : - * Default timeout for session estabishmant in units of ms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_DEFAULT_SESSION_ESTABLISHMENT_TIMEOUT 0x14BB - -/******************************************************************************* - * NAME : UnifiFtmDefaultGapBeforeFirstBurstPerResponder - * PSID : 5308 (0x14BC) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Deprecated - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_DEFAULT_GAP_BEFORE_FIRST_BURST_PER_RESPONDER 0x14BC - -/******************************************************************************* - * NAME : UnifiFtmDefaultGapBetweenBursts - * PSID : 5309 (0x14BD) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 5 - * MAX : 50 - * DEFAULT : 10 - * DESCRIPTION : - * Interval between consecutive Bursts. In units of ms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_DEFAULT_GAP_BETWEEN_BURSTS 0x14BD - -/******************************************************************************* - * NAME : UnifiFtmDefaultTriggerDelay - * PSID : 5310 (0x14BE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 1 - * DESCRIPTION : - * Delay to account for differences in time between Initiator and Responder - * at start of the Burst. In units of ms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_DEFAULT_TRIGGER_DELAY 0x14BE - -/******************************************************************************* - * NAME : UnifiFtmDefaultEndBurstDelay - * PSID : 5311 (0x14BF) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 100 - * DEFAULT : 10 - * DESCRIPTION : - * Delay to account for differences in time between Initiator and Responder - * at the end of the Burst. In units of ms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_DEFAULT_END_BURST_DELAY 0x14BF - -/******************************************************************************* - * NAME : UnifiFtmRequestValidationEnabled - * PSID : 5312 (0x14C0) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enable Validation for FTM Add Range request RTT_Configs - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_REQUEST_VALIDATION_ENABLED 0x14C0 - -/******************************************************************************* - * NAME : UnifiFtmResponseValidationEnabled - * PSID : 5313 (0x14C1) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Enable Validation for FTM Response - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_RESPONSE_VALIDATION_ENABLED 0x14C1 - -/******************************************************************************* - * NAME : UnifiFtmUseResponseParameters - * PSID : 5314 (0x14C2) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Use Response burst parameters for burst - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_USE_RESPONSE_PARAMETERS 0x14C2 - -/******************************************************************************* - * NAME : UnifiFtmInitialResponseTimeout - * PSID : 5315 (0x14C3) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 10 - * MAX : 100 - * DEFAULT : 50 - * DESCRIPTION : - * Default timeout for FtmInitialResponse in units of ms. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_FTM_INITIAL_RESPONSE_TIMEOUT 0x14C3 - -/******************************************************************************* - * NAME : UnifiMlmeScanContinueIfMoreThanXAps - * PSID : 5410 (0x1522) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Part of Scan Algorithm: Keep scanning on a channel with lots of APs. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_CONTINUE_IF_MORE_THAN_XAPS 0x1522 - -/******************************************************************************* - * NAME : UnifiMlmeScanStopIfLessThanXNewAps - * PSID : 5411 (0x1523) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 4 - * DESCRIPTION : - * Part of Scan Algorithm: Stop scanning on a channel if less than X NEW APs - * are seen. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_STOP_IF_LESS_THAN_XNEW_APS 0x1523 - -/******************************************************************************* - * NAME : UnifiMlmeScanMultiVifEnabled - * PSID : 5412 (0x1524) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : 1 - * DESCRIPTION : - * Part of Scan Algorithm: Enable support for Multi Vif channel times. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_MULTI_VIF_ENABLED 0x1524 - -/******************************************************************************* - * NAME : UnifiMlmeScanNewAlgorithmEnabled - * PSID : 5413 (0x1525) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : 1 - * DESCRIPTION : - * Part of Scan Algorithm: Enable support for the new algorithm. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_MLME_SCAN_NEW_ALGORITHM_ENABLED 0x1525 - -/******************************************************************************* - * NAME : UnifiTpcMinPower2Gmimo - * PSID : 6011 (0x177B) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : 52 - * DESCRIPTION : - * Minimum power for 2.4GHz MIMO interface when RSSI is above - * unifiTPCMinPowerRSSIThreshold (quarter dbm). Should be greater than - * dot11PowerCapabilityMinImplemented. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_MIN_POWER2_GMIMO 0x177B - -/******************************************************************************* - * NAME : UnifiTpcMinPower5Gmimo - * PSID : 6012 (0x177C) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : 52 - * DESCRIPTION : - * Minimum power for 5 GHz MIMO interface when RSSI is above - * unifiTPCMinPowerRSSIThreshold (quarter dbm). Should be greater than - * dot11PowerCapabilityMinImplemented. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_MIN_POWER5_GMIMO 0x177C - -/******************************************************************************* - * NAME : UnifiLnaControlEnabled - * PSID : 6013 (0x177D) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enable dynamic switching of the LNA based on RSSI. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LNA_CONTROL_ENABLED 0x177D - -/******************************************************************************* - * NAME : UnifiLnaControlRssiThresholdLower - * PSID : 6014 (0x177E) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dBm - * MIN : -128 - * MAX : 127 - * DEFAULT : -40 - * DESCRIPTION : - * The lower RSSI threshold for dynamic switching of the LNA. If the RSSI - * avg of received frames is lower than this value for all scheduled VIFs, - * then the external LNA will be enabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LNA_CONTROL_RSSI_THRESHOLD_LOWER 0x177E - -/******************************************************************************* - * NAME : UnifiLnaControlRssiThresholdUpper - * PSID : 6015 (0x177F) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dBm - * MIN : -128 - * MAX : 127 - * DEFAULT : -30 - * DESCRIPTION : - * The upper RSSI threshold for dynamic switching of the LNA. If the RSSI - * avg of received frames is higher than this value for all scheduled VIFs, - * then the external LNA will be disabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LNA_CONTROL_RSSI_THRESHOLD_UPPER 0x177F - -/******************************************************************************* - * NAME : UnifiPowerIsGrip - * PSID : 6016 (0x1780) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Is using Grip power cap instead of SAR cap. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_POWER_IS_GRIP 0x1780 - -/******************************************************************************* - * NAME : UnifiTpcEnabled - * PSID : 6019 (0x1783) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : - * DESCRIPTION : - * Deprecated. Golden Certification MIB don't delete, change PSID or name - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_ENABLED 0x1783 - -/******************************************************************************* - * NAME : UnifiCurrentTxpowerLevel - * PSID : 6020 (0x1784) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : qdBm - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Maximum air power for the VIF. Values are expressed in 0.25 dBm units. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_CURRENT_TXPOWER_LEVEL 0x1784 - -/******************************************************************************* - * NAME : UnifiUserSetTxpowerLevel - * PSID : 6021 (0x1785) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : 127 - * DESCRIPTION : - * Test only: Maximum User Set Tx Power (quarter dBm). Enable it in - * unifiTestTxPowerEnable. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_USER_SET_TXPOWER_LEVEL 0x1785 - -/******************************************************************************* - * NAME : UnifiTpcMaxPowerRssiThreshold - * PSID : 6022 (0x1786) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : -55 - * DESCRIPTION : - * Below the (dBm) threshold, switch to the max power allowed by regulatory, - * if it has been previously reduced due to unifiTPCMinPowerRSSIThreshold. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_MAX_POWER_RSSI_THRESHOLD 0x1786 - -/******************************************************************************* - * NAME : UnifiTpcMinPowerRssiThreshold - * PSID : 6023 (0x1787) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : -45 - * DESCRIPTION : - * Above the (dBm) threshold, switch to the minimum hardware supported - - * capped by unifiTPCMinPower2G/unifiTPCMinPower5G. A Zero value reverts the - * power to a default state. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_MIN_POWER_RSSI_THRESHOLD 0x1787 - -/******************************************************************************* - * NAME : UnifiTpcMinPower2g - * PSID : 6024 (0x1788) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : 52 - * DESCRIPTION : - * Minimum power for 2.4GHz SISO interface when RSSI is above - * unifiTPCMinPowerRSSIThreshold (quarter dbm). Should be greater than - * dot11PowerCapabilityMinImplemented. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_MIN_POWER2G 0x1788 - -/******************************************************************************* - * NAME : UnifiTpcMinPower5g - * PSID : 6025 (0x1789) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : 40 - * DESCRIPTION : - * Minimum power for 5 GHz SISO interface when RSSI is above - * unifiTPCMinPowerRSSIThreshold (quarter dbm). Should be greater than - * dot11PowerCapabilityMinImplemented. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_MIN_POWER5G 0x1789 - -/******************************************************************************* - * NAME : UnifiSarBackoff - * PSID : 6026 (0x178A) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Max power values per band per index(quarter dBm). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SAR_BACKOFF 0x178A - -/******************************************************************************* - * NAME : UnifiTpcUseAfterConnectRsp - * PSID : 6027 (0x178B) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Use TPC only after MlmeConnect_Rsp has been received from the Host i.e. - * not during initial connection exchanges (EAPOL/DHCP operation) as RSSI - * readings might be inaccurate. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TPC_USE_AFTER_CONNECT_RSP 0x178B - -/******************************************************************************* - * NAME : UnifiRadioLpRxRssiThresholdLower - * PSID : 6028 (0x178C) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dBm - * MIN : -128 - * MAX : 127 - * DEFAULT : -75 - * DESCRIPTION : - * The lower RSSI threshold for switching between low power rx and normal - * rx. If the RSSI avg of received frames is lower than this value for a - * VIF, then that VIF will vote against using low-power radio RX. Low power - * rx could negatively influence the receiver sensitivity. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_LP_RX_RSSI_THRESHOLD_LOWER 0x178C - -/******************************************************************************* - * NAME : UnifiRadioLpRxRssiThresholdUpper - * PSID : 6029 (0x178D) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * UNITS : dBm - * MIN : -128 - * MAX : 127 - * DEFAULT : -65 - * DESCRIPTION : - * The upper RSSI threshold for switching between low power rx and normal - * rx. If the RSSI avg of received frames is higher than this value for a - * VIF, then that VIF will vote in favour of using low-power radio RX. Low - * power RX could negatively influence the receiver sensitivity. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_RADIO_LP_RX_RSSI_THRESHOLD_UPPER 0x178D - -/******************************************************************************* - * NAME : UnifiTestTxPowerEnable - * PSID : 6032 (0x1790) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X03DD - * DESCRIPTION : - * Test only: Bitfield to enable Control Plane Tx Power processing. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TEST_TX_POWER_ENABLE 0x1790 - -/******************************************************************************* - * NAME : UnifiLteCoexMaxPowerRssiThreshold - * PSID : 6033 (0x1791) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : -55 - * DESCRIPTION : - * Below this (dBm) threshold, switch to max power allowed by regulatory, if - * it has been previously reduced due to unifiTPCMinPowerRSSIThreshold. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_COEX_MAX_POWER_RSSI_THRESHOLD 0x1791 - -/******************************************************************************* - * NAME : UnifiLteCoexMinPowerRssiThreshold - * PSID : 6034 (0x1792) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : -45 - * DESCRIPTION : - * Above this(dBm) threshold, switch to minimum hardware supported - capped - * by unifiTPCMinPower2G/unifiTPCMinPower5G. Zero reverts the power to its - * default state. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_COEX_MIN_POWER_RSSI_THRESHOLD 0x1792 - -/******************************************************************************* - * NAME : UnifiLteCoexPowerReduction - * PSID : 6035 (0x1793) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 127 - * DEFAULT : 24 - * DESCRIPTION : - * When LTE Coex Power Reduction provisions are met, impose a power cap of - * the regulatory domain less the amount specified by this MIB (quarter dB) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LTE_COEX_POWER_REDUCTION 0x1793 - -/******************************************************************************* - * NAME : UnifiPmfAssociationComebackTimeDelta - * PSID : 6050 (0x17A2) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 1100 - * DESCRIPTION : - * Timeout interval, in TU, for the TimeOut IE in the SA Query request - * frame. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_PMF_ASSOCIATION_COMEBACK_TIME_DELTA 0x17A2 - -/******************************************************************************* - * NAME : UnifiTestTspecHack - * PSID : 6060 (0x17AC) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Test only: Hack to allow in-house tspec testing - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TEST_TSPEC_HACK 0x17AC - -/******************************************************************************* - * NAME : UnifiTestTspecHackValue - * PSID : 6061 (0x17AD) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Test only: Saved dialog number of tspec request action frame from the - * Host - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TEST_TSPEC_HACK_VALUE 0x17AD - -/******************************************************************************* - * NAME : UnifiDebugInstantDelivery - * PSID : 6069 (0x17B5) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Instant delivery control of the debug messages when set to true. Note: - * will not allow the host to suspend when set to True. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEBUG_INSTANT_DELIVERY 0x17B5 - -/******************************************************************************* - * NAME : UnifiDebugEnable - * PSID : 6071 (0x17B7) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Debug to host state. Debug is either is sent to the host or it isn't. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEBUG_ENABLE 0x17B7 - -/******************************************************************************* - * NAME : UnifiDPlaneDebug - * PSID : 6073 (0x17B9) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X03 - * DESCRIPTION : - * Bit mask for turning on individual debug entities in the data_plane that - * if enabled effect throughput. See DPLP_DEBUG_ENTITIES_T in - * dplane_dplp_debug.h for bits. Default of 0x3 means dplp and ampdu logs - * are enabled. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DPLANE_DEBUG 0x17B9 - -/******************************************************************************* - * NAME : UnifiNanEnabled - * PSID : 6080 (0x17C0) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Enables Neighbour Aware Networking (NAN) - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_ENABLED 0x17C0 - -/******************************************************************************* - * NAME : UnifiNanBeaconCapabilities - * PSID : 6081 (0x17C1) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X0720 - * DESCRIPTION : - * The 16-bit field follows the coding of IEEE 802.11 Capability - * Information. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_BEACON_CAPABILITIES 0x17C1 - -/******************************************************************************* - * NAME : UnifiNanMaxConcurrentClusters - * PSID : 6082 (0x17C2) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 1 - * DESCRIPTION : - * Maximum number of concurrent NAN clusters supported. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_CLUSTERS 0x17C2 - -/******************************************************************************* - * NAME : UnifiNanMaxConcurrentPublishes - * PSID : 6083 (0x17C3) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2 - * DESCRIPTION : - * Maximum number of concurrent NAN Publish instances supported. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_PUBLISHES 0x17C3 - -/******************************************************************************* - * NAME : UnifiNanMaxConcurrentSubscribes - * PSID : 6084 (0x17C4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 2 - * DESCRIPTION : - * Maximum number of concurrent NAN Subscribe instances supported. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_SUBSCRIBES 0x17C4 - -/******************************************************************************* - * NAME : UnifiNanMaxServiceNameLength - * PSID : 6085 (0x17C5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 255 - * DESCRIPTION : - * Maximum Service Name Length. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_SERVICE_NAME_LENGTH 0x17C5 - -/******************************************************************************* - * NAME : UnifiNanMaxMatchFilterLength - * PSID : 6086 (0x17C6) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 255 - * DESCRIPTION : - * Maximum Match Filter Length. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_MATCH_FILTER_LENGTH 0x17C6 - -/******************************************************************************* - * NAME : UnifiNanMaxTotalMatchFilterLength - * PSID : 6087 (0x17C7) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 255 - * DESCRIPTION : - * Maximum Total Match Filter Length. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_TOTAL_MATCH_FILTER_LENGTH 0x17C7 - -/******************************************************************************* - * NAME : UnifiNanMaxServiceSpecificInfoLength - * PSID : 6088 (0x17C8) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 255 - * DESCRIPTION : - * Maximum Service Specific Info Length. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_SERVICE_SPECIFIC_INFO_LENGTH 0x17C8 - -/******************************************************************************* - * NAME : UnifiNanMaxVsaDataLength - * PSID : 6089 (0x17C9) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Maximum Vendor Specific Attribute Data Length. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_VSA_DATA_LENGTH 0x17C9 - -/******************************************************************************* - * NAME : UnifiNanMaxMeshDataLength - * PSID : 6090 (0x17CA) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Maximum Mesh Data Length. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_MESH_DATA_LENGTH 0x17CA - -/******************************************************************************* - * NAME : UnifiNanMaxNdiInterfaces - * PSID : 6091 (0x17CB) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Maximum NDI Interfaces. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_NDI_INTERFACES 0x17CB - -/******************************************************************************* - * NAME : UnifiNanMaxNdpSessions - * PSID : 6092 (0x17CC) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Maximum NDP Sessions. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_NDP_SESSIONS 0x17CC - -/******************************************************************************* - * NAME : UnifiNanMaxAppInfoLength - * PSID : 6093 (0x17CD) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Maximum App Info Length. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NAN_MAX_APP_INFO_LENGTH 0x17CD - -/******************************************************************************* - * NAME : ReservedForNan - * PSID : 6094 (0x17CE) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 3 - * DESCRIPTION : - * Enables low power radio RX for idle STA and AP VIFs respectively. - * Setting/clearing bit 0 enables/disabled LP RX for (all) STA/Cli VIFs. - * Setting/clearing bit 1 enables/disabled LP RX for AP/GO VIFs.This mib - * value will be updated if "unifiRameUpdateMibs" mib is toggled - *******************************************************************************/ -#define SLSI_PSID_RESERVED_FOR_NAN 0x17CE - -/******************************************************************************* - * NAME : hutsReadWriteDataElementInt32 - * PSID : 6100 (0x17D4) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 1000 - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of int32 type. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_DATA_ELEMENT_INT32 0x17D4 - -/******************************************************************************* - * NAME : hutsReadWriteDataElementBoolean - * PSID : 6101 (0x17D5) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of boolean type. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_DATA_ELEMENT_BOOLEAN 0x17D5 - -/******************************************************************************* - * NAME : hutsReadWriteDataElementOctetString - * PSID : 6102 (0x17D6) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 9 - * MAX : 9 - * DEFAULT : { 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of octet string - * type. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_DATA_ELEMENT_OCTET_STRING 0x17D6 - -/******************************************************************************* - * NAME : hutsReadWriteTableInt16Row - * PSID : 6103 (0x17D7) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry table of int16 - * type. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_TABLE_INT16_ROW 0x17D7 - -/******************************************************************************* - * NAME : hutsReadWriteTableOctetStringRow - * PSID : 6104 (0x17D8) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 6 - * MAX : 73 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry table of octet - * string type. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_TABLE_OCTET_STRING_ROW 0x17D8 - -/******************************************************************************* - * NAME : hutsReadWriteRemoteProcedureCallInt32 - * PSID : 6105 (0x17D9) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : 0X000A0001 - * DESCRIPTION : - * Reserved for HUTS tests - Remote Procedure call read/write entry of int32 - * type. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_REMOTE_PROCEDURE_CALL_INT32 0x17D9 - -/******************************************************************************* - * NAME : hutsReadWriteRemoteProcedureCallOctetString - * PSID : 6107 (0x17DB) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 144 - * MAX : 144 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Remote Procedure call read/write entry of octet - * string type. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_REMOTE_PROCEDURE_CALL_OCTET_STRING 0x17DB - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiInt16 - * PSID : 6108 (0x17DC) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : -55 - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of int16 type via - * internal API. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_INT16 0x17DC - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiUint16 - * PSID : 6109 (0x17DD) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 0X0730 - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of unsigned int16 - * type via internal API. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_UINT16 0x17DD - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiUint32 - * PSID : 6110 (0x17DE) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * UNITS : microseconds - * MIN : 0 - * MAX : 2147483647 - * DEFAULT : 30000 - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of unsigned int32 - * type via internal API. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_UINT32 0x17DE - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiInt64 - * PSID : 6111 (0x17DF) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : -9223372036854775808 - * MAX : 9223372036854775807 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of int64 type via - * internal API. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_INT64 0x17DF - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiBoolean - * PSID : 6112 (0x17E0) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : TRUE - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of boolean type - * via internal API. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_BOOLEAN 0x17E0 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiOctetString - * PSID : 6113 (0x17E1) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 8 - * MAX : 8 - * DEFAULT : { 0X00, 0X18, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * Reserved for HUTS tests - Data element read/write entry of octet string - * type via internal API. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_OCTET_STRING 0x17E1 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiFixedSizeTableRow - * PSID : 6114 (0x17E2) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : 0 - * MAX : 100 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Fixed size table rows of int16 type via - * internal API - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_FIXED_SIZE_TABLE_ROW 0x17E2 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiVarSizeTableRow - * PSID : 6115 (0x17E3) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 6 - * MAX : 73 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Variable size table rows of octet string type - * via internal API - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_VAR_SIZE_TABLE_ROW 0x17E3 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiFixSizeTableKey1Row - * PSID : 6116 (0x17E4) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Fixed size table rows of int16 type via - * internal API - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_FIX_SIZE_TABLE_KEY1_ROW 0x17E4 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiFixSizeTableKey2Row - * PSID : 6117 (0x17E5) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Reserved for HUTS tests - Fixed size table rows of int16 type via - * internal API - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_FIX_SIZE_TABLE_KEY2_ROW 0x17E5 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiFixVarSizeTableKey1Row - * PSID : 6118 (0x17E6) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The values stored in hutsReadWriteInternalAPIFixVarSizeTableKeys - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_FIX_VAR_SIZE_TABLE_KEY1_ROW 0x17E6 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiFixVarSizeTableKey2Row - * PSID : 6119 (0x17E7) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * The values stored in hutsReadWriteInternalAPIFixVarSizeTableKeys - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_FIX_VAR_SIZE_TABLE_KEY2_ROW 0x17E7 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiFixSizeTableKeyRow - * PSID : 6120 (0x17E8) - * PER INTERFACE?: NO - * TYPE : INT64 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * The number of received MPDUs discarded by the CCMP decryption algorithm. - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_FIX_SIZE_TABLE_KEY_ROW 0x17E8 - -/******************************************************************************* - * NAME : hutsReadWriteInternalApiVarSizeTableKeyRow - * PSID : 6121 (0x17E9) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 144 - * MAX : 144 - * DEFAULT : - * DESCRIPTION : - * Write a DPD LUT entry - *******************************************************************************/ -#define SLSI_PSID_HUTS_READ_WRITE_INTERNAL_API_VAR_SIZE_TABLE_KEY_ROW 0x17E9 - -/******************************************************************************* - * NAME : UnifiTestScanNoMedium - * PSID : 6122 (0x17EA) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Test only: Stop Scan from using the Medium to allow thruput testing. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_TEST_SCAN_NO_MEDIUM 0x17EA - -/******************************************************************************* - * NAME : UnifiDualBandConcurrency - * PSID : 6123 (0x17EB) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Identify whether the chip supports dualband concurrency or not (RSDB vs. - * VSDB). Set in the respective platform htf file. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DUAL_BAND_CONCURRENCY 0x17EB - -/******************************************************************************* - * NAME : UnifiLoggerMaxDelayedEvents - * PSID : 6124 (0x17EC) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : 10 - * DESCRIPTION : - * Maximum number of events to keep when host is suspended. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_LOGGER_MAX_DELAYED_EVENTS 0x17EC - -/******************************************************************************* - * NAME : UnifiRegulatoryParameters - * PSID : 8011 (0x1F4B) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 3 - * MAX : 73 - * DEFAULT : - * DESCRIPTION : - * Regulatory parameters. Each row of the table contains the regulatory - * rules for one country: octet 0 - first character of alpha2 code for - * country octet 1 - second character of alpha2 code for country octet 2 - - * regulatory domain for the country Followed by the rules for the country, - * numbered 0..n in this description octet 7n+3 - LSB start frequency octet - * 7n+4 - MSB start frequency octet 7n+5 - LSB end frequency octet 7n+6 - - * MSB end frequency octet 7n+7 - maximum bandwidth octet 7n+8 - maximum - * power octet 7n+9 - rule flags - *******************************************************************************/ -#define SLSI_PSID_UNIFI_REGULATORY_PARAMETERS 0x1F4B - -/******************************************************************************* - * NAME : UnifiSupportedChannels - * PSID : 8012 (0x1F4C) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 20 - * DEFAULT : {0X01,0X0D,0X24,0X04,0X34,0X04,0X64,0X0C,0X95,0X05} - * DESCRIPTION : - * Supported 20MHz channel centre frequency grouped in sub-bands. For each - * sub-band: starting channel number, followed by number of channels - *******************************************************************************/ -#define SLSI_PSID_UNIFI_SUPPORTED_CHANNELS 0x1F4C - -/******************************************************************************* - * NAME : UnifiDefaultCountry - * PSID : 8013 (0x1F4D) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 3 - * MAX : 3 - * DEFAULT : {0X30, 0X30, 0X20} - * DESCRIPTION : - * Hosts sets the Default Code. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEFAULT_COUNTRY 0x1F4D - -/******************************************************************************* - * NAME : UnifiCountryList - * PSID : 8014 (0x1F4E) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 2 - * MAX : 270 - * DEFAULT : (Too Large to display) - * DESCRIPTION : - * Defines the ordered list of countries present in unifiRegulatoryTable. - * Each country is coded as 2 ASCII characters. If unifiRegulatoryTable is - * modified, such as a country is either added, deleted or its relative - * location is modified, has to be updated as well. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_COUNTRY_LIST 0x1F4E - -/******************************************************************************* - * NAME : UnifiOperatingClassParamters - * PSID : 8015 (0x1F4F) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 1 - * MAX : 73 - * DEFAULT : - * DESCRIPTION : - * Supported Operating Class parameters. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_OPERATING_CLASS_PARAMTERS 0x1F4F - -/******************************************************************************* - * NAME : UnifiVifCountry - * PSID : 8016 (0x1F50) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Per VIf: Each VIF updates its Country Code for the Host to read - *******************************************************************************/ -#define SLSI_PSID_UNIFI_VIF_COUNTRY 0x1F50 - -/******************************************************************************* - * NAME : UnifiNoCellMaxPower - * PSID : 8017 (0x1F51) - * PER INTERFACE?: NO - * TYPE : SlsiInt16 - * MIN : -32768 - * MAX : 32767 - * DEFAULT : - * DESCRIPTION : - * Max power values for included channels (quarter dBm). - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NO_CELL_MAX_POWER 0x1F51 - -/******************************************************************************* - * NAME : UnifiNoCellIncludedChannels - * PSID : 8018 (0x1F52) - * PER INTERFACE?: NO - * TYPE : SlsiUint8 - * MIN : 8 - * MAX : 8 - * DEFAULT : { 0X00, 0X18, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 } - * DESCRIPTION : - * Channels applicable. Defined in a uint64 represented by the octet string. - * First byte of the octet string maps to LSB. Bit 0 maps to channel 1. - * Mapping defined in ChannelisationRules. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_NO_CELL_INCLUDED_CHANNELS 0x1F52 - -/******************************************************************************* - * NAME : UnifiRegDomVersion - * PSID : 8019 (0x1F53) - * PER INTERFACE?: NO - * TYPE : SlsiUint16 - * MIN : 0 - * MAX : 65535 - * DEFAULT : - * DESCRIPTION : - * Regulatory domain version encoded into 2 bytes, major version as MSB and - * minor version as LSB - *******************************************************************************/ -#define SLSI_PSID_UNIFI_REG_DOM_VERSION 0x1F53 - -/******************************************************************************* - * NAME : UnifiDefaultCountryWithoutCH12CH13 - * PSID : 8020 (0x1F54) - * PER INTERFACE?: NO - * TYPE : SlsiBool - * MIN : 0 - * MAX : 1 - * DEFAULT : FALSE - * DESCRIPTION : - * Update the default country code to ensure CH12 and CH13 are not used. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_DEFAULT_COUNTRY_WITHOUT_CH12_CH13 0x1F54 - -/******************************************************************************* - * NAME : UnifiReadReg - * PSID : 8051 (0x1F73) - * PER INTERFACE?: NO - * TYPE : SlsiUint32 - * MIN : 0 - * MAX : 4294967295 - * DEFAULT : - * DESCRIPTION : - * Read value from a register and return it. - *******************************************************************************/ -#define SLSI_PSID_UNIFI_READ_REG 0x1F73 - -#ifdef __cplusplus -} -#endif -#endif /* SLSI_MIB_H__ */ diff --git a/drivers/net/wireless/scsc/mib_text_convert.c b/drivers/net/wireless/scsc/mib_text_convert.c deleted file mode 100644 index dc6e63eb81ae..000000000000 --- a/drivers/net/wireless/scsc/mib_text_convert.c +++ /dev/null @@ -1,327 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd and its Licensors. - * All rights reserved. - * - *****************************************************************************/ - -#include "debug.h" -#include "mib_text_convert.h" - -#define CSR_TOUPPER(character) (((character) >= 'a') && ((character) <= 'z') ? ((character) - 0x20) : (character)) - -static inline bool CsrIsSpace(u8 c) -{ - switch (c) { - case '\t': - case '\n': - case '\f': - case '\r': - case ' ': - return true; - default: - return false; - } -} - -static inline char *CsrStrDup(const char *string) -{ - if (string != NULL) { - u32 len = strlen(string) + 1; - - return memcpy(kmalloc(len, GFP_KERNEL), string, len); - } - return NULL; -} - -static int CsrStrNICmp(const char *string1, - const char *string2, - size_t count) -{ - u32 index; - int returnValue = 0; - - for (index = 0; index < count; index++) { - if (CSR_TOUPPER(string1[index]) != CSR_TOUPPER(string2[index])) { - if (CSR_TOUPPER(string1[index]) > CSR_TOUPPER(string2[index])) - returnValue = 1; - else - returnValue = -1; - break; - } - if (string1[index] == '\0') - break; - } - return returnValue; -} - -static bool CsrHexStrToUint8(const char *string, u8 *returnValue) -{ - u16 currentIndex = 0; - - *returnValue = 0; - if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X')) - string += 2; - if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) { - while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) { - *returnValue = (u8)(*returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10)); - currentIndex++; - if (currentIndex >= 2) - break; - } - return true; - } - return false; -} - -static bool CsrHexStrToUint16(const char *string, u16 *returnValue) -{ - u16 currentIndex = 0; - - *returnValue = 0; - if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X')) - string += 2; - if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) { - while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) { - *returnValue = (u16)(*returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10)); - currentIndex++; - if (currentIndex >= 4) - break; - } - return true; - } - return false; -} - -static bool CsrHexStrToUint32(const char *string, u32 *returnValue) -{ - u16 currentIndex = 0; - - *returnValue = 0; - if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X')) - string += 2; - if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) { - while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) { - *returnValue = *returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10); - currentIndex++; - if (currentIndex >= 8) - break; - } - return true; - } - return false; -} - -static bool CsrWifiMibConvertStrToUint16(const char *str, u16 *returnValue) -{ - u16 currentIndex = 0; - - if (str[1] == 'x') - return CsrHexStrToUint16(str, returnValue); - - *returnValue = 0; - if ((str[currentIndex] >= '0') && (str[currentIndex] <= '9')) { - while (str[currentIndex] >= '0' && str[currentIndex] <= '9') { - *returnValue *= 10; - *returnValue += (u8)str[currentIndex++] - '0'; - } - return true; - } - return false; -} - -static bool CsrWifiMibConvertStrToUint32(const char *str, u32 *returnValue) -{ - u16 currentIndex = 0; - - if (str[1] == 'x') - return CsrHexStrToUint32(str, returnValue); - - *returnValue = 0; - if ((str[currentIndex] >= '0') && (str[currentIndex] <= '9')) { - while (str[currentIndex] >= '0' && str[currentIndex] <= '9') { - *returnValue *= 10; - *returnValue += (u8)str[currentIndex++] - '0'; - } - return true; - } - return false; -} - -static bool CsrWifiMibConvertTextParseLine(const char *linestr, struct slsi_mib_data *mibDataSet, struct slsi_mib_data *mibDataGet) -{ - struct slsi_mib_entry entry; - bool result = true; - size_t equals = 0; - size_t dot1 = 0; - size_t dot2 = 0; - size_t trimmedIndex = 0; - char *trimmed = kmalloc(strlen(linestr) + 1, GFP_KERNEL); - const char *current_char = linestr; - bool processingStr = false; - - memset(&entry, 0x00, sizeof(entry)); - while (current_char[0] != '\0') { - if (current_char[0] == '"') - processingStr = !processingStr; - if (!processingStr) { - if (current_char[0] == '#') - break; - if (CsrIsSpace((u8)current_char[0])) { - current_char++; - continue; - } - if (!equals && (current_char[0] == '.')) { - if (!dot1) { - dot1 = trimmedIndex; - } else if (!dot2) { - dot2 = trimmedIndex; - } else { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') only 2 indexes supported", trimmed); - result = false; - } - } - if (!equals && (current_char[0] == '=')) - equals = trimmedIndex; - } - trimmed[trimmedIndex++] = current_char[0]; - - current_char++; - } - trimmed[trimmedIndex] = '\0'; - - if (strlen(trimmed) == 0) { - kfree(trimmed); - return result; - } - - if (result) { - char sep = trimmed[dot1 ? dot1 : equals]; - - if (dot1 || equals) - trimmed[dot1 ? dot1 : equals] = '\0'; - trimmed[dot1 ? dot1 : equals] = sep; - - if (!CsrWifiMibConvertStrToUint16(trimmed, &entry.psid)) { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert failed", trimmed); - result = false; - } - if (dot1 && !CsrWifiMibConvertStrToUint16(&trimmed[dot1 + 1], &entry.index[0])) { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert failed", trimmed); - result = false; - } - if (dot2 && !CsrWifiMibConvertStrToUint16(&trimmed[dot2 + 1], &entry.index[1])) { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert failed", trimmed); - result = false; - } - - if (result && !equals && mibDataGet) { - entry.value.type = SLSI_MIB_TYPE_NONE; - (void)slsi_mib_encode(mibDataGet, &entry); - } - - if (result && equals && mibDataSet) { - char *data = &trimmed[equals + 1]; - /*SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') psid:%d, index1:%d, index2:%d, data '%s'", trimmed, entry.psid, entry.index[0], entry.index[1], data); */ - if (CsrStrNICmp(data, "true", 4) == 0) { - entry.value.type = SLSI_MIB_TYPE_BOOL; - entry.value.u.boolValue = 1; - } else if (CsrStrNICmp(data, "false", 5) == 0) { - entry.value.type = SLSI_MIB_TYPE_BOOL; - entry.value.u.boolValue = 0; - } else if (data[0] == '"') { - /* Null Terminated String */ - entry.value.type = SLSI_MIB_TYPE_OCTET; - entry.value.u.octetValue.dataLength = (u32)strlen(&data[1]); - entry.value.u.octetValue.data = (u8 *)CsrStrDup(&data[1]); - entry.value.u.octetValue.data[entry.value.u.octetValue.dataLength - 1] = '\0'; - } else if (data[0] == '[') { - /* Octet String */ - size_t i; - u16 octetLen = ((u16)strlen(&data[1]) - 1) / 2; - - entry.value.type = SLSI_MIB_TYPE_OCTET; - entry.value.u.octetValue.dataLength = octetLen; - entry.value.u.octetValue.data = kmalloc(entry.value.u.octetValue.dataLength + 1, GFP_KERNEL); - for (i = 0; i < octetLen; i++) - if (!CsrHexStrToUint8(&data[1 + (i * 2)], &entry.value.u.octetValue.data[i])) { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert Hex Bytes failed", trimmed); - result = false; - break; - } - entry.value.u.octetValue.data[octetLen] = '\0'; /* Make sure the Octet Stream is NULL terminated in case it is interpreted as a String */ - } else if (data[0] == '-') { - /* Negative Integer Value */ - entry.value.type = SLSI_MIB_TYPE_INT; - if (!CsrWifiMibConvertStrToUint32(&data[1], &entry.value.u.uintValue)) { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert Integer failed", trimmed); - result = false; - } else { - entry.value.u.intValue = (s32)(0 - (u32)entry.value.u.uintValue); - } - } else if (!CsrWifiMibConvertStrToUint32(data, &entry.value.u.uintValue)) { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert Unsigned Integer failed", trimmed); - result = false; - } else { - entry.value.type = SLSI_MIB_TYPE_UINT; - } - if (result) - (void)slsi_mib_encode(mibDataSet, &entry); - if (entry.value.type == SLSI_MIB_TYPE_OCTET) - kfree(entry.value.u.octetValue.data); - } - } - - kfree(trimmed); - - return result; -} - -static bool CsrWifiMibConvertTextAppend(const char *mibText, struct slsi_mib_data *mibDataSet, struct slsi_mib_data *mibDataGet) -{ - bool result = true; - const char *lineStart = mibText; - const char *lineEnd = mibText; - - if (mibText == NULL) - return false; - - while (lineEnd[0] != '\0') { - if ((lineEnd[0] == '\n') || (lineEnd[0] == '\r') || (lineEnd[1] == '\0')) { - size_t strSize = (size_t)(lineEnd - lineStart); - - if ((lineEnd[1] == '\0')) - strSize++; - if (strSize > 2) { - char *line = kmalloc(strSize + 1, GFP_KERNEL); - (void)strncpy(line, lineStart, strSize); - line[strSize] = '\0'; - if (!CsrWifiMibConvertTextParseLine(line, mibDataSet, mibDataGet)) { - SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine() Failed for line '%s'", line); - result = false; - } - kfree(line); - } - lineEnd++; - lineStart = lineEnd; - continue; - } - lineEnd++; - } - - return result; -} - -bool CsrWifiMibConvertText(const char *mibText, struct slsi_mib_data *mibDataSet, struct slsi_mib_data *mibDataGet) -{ - if (mibDataSet) { - mibDataSet->data = NULL; - mibDataSet->dataLength = 0; - } - if (mibDataGet) { - mibDataGet->data = NULL; - mibDataGet->dataLength = 0; - } - - return CsrWifiMibConvertTextAppend(mibText, mibDataSet, mibDataGet); -} diff --git a/drivers/net/wireless/scsc/mib_text_convert.h b/drivers/net/wireless/scsc/mib_text_convert.h deleted file mode 100644 index 0864f7488d6d..000000000000 --- a/drivers/net/wireless/scsc/mib_text_convert.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd and its Licensors. - * All rights reserved. - * - *****************************************************************************/ - -#ifndef MIB_TEXT_CONVERT_H__ -#define MIB_TEXT_CONVERT_H__ - -#include "mib.h" - -/******************************************************************************* - * - * NAME - * CsrWifiMibConvertText - * - * DESCRIPTION - * Converts a simple text mib file format into an encoded mib data buffer - * - * TEXT FILE FORMAT - # Comment - # = - # - # 123 = 0x01 # Unsigned Integer - # 123 = 1 # Unsigned Integer - # 123 = -1 # Integer - # 123 = true # Boolean (Case Sensitive) - # 123 = false # Boolean (Case Sensitive) - # 123 = [12183984] # Octet String (Hex Format) - # 123 = "ABCDEFGH" # Octet String (Null Terminated Ascii) - # - # Indexes (Max 2 indexes supported) - # 123.1 = 1 # Single Index - # 123.1.2 = 1 # Multi Index - # - # Hex Format (All Unsigned Integer values can use the alternative 0x[0-F] format) - # 0xF12E.0x1.0x2 = 0x01 # Unsigned Integer - # - # RETURN - # bool: true = No errors in conversion - # - *******************************************************************************/ -bool CsrWifiMibConvertText(const char *mibText, struct slsi_mib_data *mibDataSet, struct slsi_mib_data *mibDataGet); - -#endif /* MIB_TEXT_CONVERT_H__ */ diff --git a/drivers/net/wireless/scsc/mlme.c b/drivers/net/wireless/scsc/mlme.c deleted file mode 100755 index 1219633b5c1b..000000000000 --- a/drivers/net/wireless/scsc/mlme.c +++ /dev/null @@ -1,4448 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include - -#include "dev.h" -#include "debug.h" -#include "mlme.h" -#include "mib.h" -#include "mgt.h" -#include "cac.h" - -#define SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN 7 -#define SLSI_SCAN_PRIVATE_IE_SSID_FILTER_HEADER_LEN 7 -#define SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE 3 -#define SLSI_CHANN_INFO_HT_SCB 0x0100 - -#define SLSI_NOA_CONFIG_REQUEST_ID (1) -#define SLSI_MLME_ARP_DROP_FREE_SLOTS_COUNT 16 - -static bool missing_cfm_ind_panic = true; -module_param(missing_cfm_ind_panic, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(missing_cfm_ind_panic, "Panic on missing confirm or indication from the chip"); - -struct slsi_mlme_rsse { - u8 group_cs_count; - const u8 *group_cs; - u8 pairwise_cs_count; - const u8 *pairwise_cs; - u8 akm_suite_count; - const u8 *akm_suite; - u8 pmkid_count; - const u8 *pmkid; - const u8 *group_mgmt_cs; /* used for PMF*/ -}; - -static struct sk_buff *slsi_mlme_wait_for_cfm(struct slsi_dev *sdev, struct slsi_sig_send *sig_wait) -{ - struct sk_buff *cfm = NULL; - int tm; - - tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(*sdev->sig_wait_cfm_timeout)); - spin_lock_bh(&sig_wait->send_signal_lock); - - /* Confirm timed out? */ - if (!sig_wait->cfm) { - SLSI_ERR(sdev, "No cfm(0x%.4X) for req(0x%04X) senderid=0x%x\n", sig_wait->cfm_id, sig_wait->req_id, sig_wait->process_id); - if (tm == 0) { - char reason[80]; - - WARN(1, "Timeout - confirm 0x%04x not received from chip\n", sig_wait->cfm_id); - if (missing_cfm_ind_panic) { - snprintf(reason, sizeof(reason), "Timed out while waiting for the cfm(0x%.4x) for req(0x%04x)", - sig_wait->cfm_id, sig_wait->req_id); - - spin_unlock_bh(&sig_wait->send_signal_lock); - slsi_sm_service_failed(sdev, reason); - spin_lock_bh(&sig_wait->send_signal_lock); - } - } else { - WARN(1, "Confirm 0x%04x lost\n", sig_wait->cfm_id); - } - } else { - WARN_ON(fapi_get_u16(sig_wait->cfm, receiver_pid) != sig_wait->process_id); - WARN_ON(fapi_get_u16(sig_wait->cfm, id) != sig_wait->cfm_id); - } - - sig_wait->cfm_id = 0; - cfm = sig_wait->cfm; - sig_wait->cfm = NULL; - if (!cfm) - sig_wait->ind_id = 0; - - spin_unlock_bh(&sig_wait->send_signal_lock); - - return cfm; -} - -static int panic_on_lost_ind(u16 ind_id) -{ - if (ind_id == MLME_SCAN_DONE_IND) - return 0; - return 1; -} - -static struct sk_buff *slsi_mlme_wait_for_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_sig_send *sig_wait, u16 ind_id) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *ind = NULL; - int tm = 0; - - /* The indication and confirm may have been received in the same HIP read. - * The HIP receive buffer processes all received signals in one thread whilst the - * waiting process may not be scheduled even if the "complete" call is made. - * In this scenario, the complete() call has already been made for this object - * and the wait will return immediately. - */ - if (ind_id == MLME_SCAN_DONE_IND) - /* To handle the coex scenario where BTscan has high priority increasing the wait time to 40 secs */ - tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(SLSI_SCAN_DONE_IND_WAIT_TIMEOUT)); - else if ((ind_id == MLME_DISCONNECT_IND) && (ndev_vif->vif_type == FAPI_VIFTYPE_AP)) - tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(sdev->device_config.ap_disconnect_ind_timeout)); - else - tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(*sdev->sig_wait_cfm_timeout)); - - spin_lock_bh(&sig_wait->send_signal_lock); - - /* Indication timed out? */ - if (!sig_wait->ind) { - SLSI_ERR(sdev, "No ind(0x%.4X) for req(0x%04X) senderid=0x%x\n", sig_wait->ind_id, sig_wait->req_id, sig_wait->process_id); - if (tm == 0) { - char reason[80]; - - WARN(1, "Timeout - indication 0x%04x not received from chip\n", sig_wait->ind_id); - if (missing_cfm_ind_panic && panic_on_lost_ind(ind_id)) { - snprintf(reason, sizeof(reason), "Timed out while waiting for the ind(0x%.4x) for req(0x%04x)", - sig_wait->ind_id, sig_wait->req_id); - - spin_unlock_bh(&sig_wait->send_signal_lock); - slsi_sm_service_failed(sdev, reason); - spin_lock_bh(&sig_wait->send_signal_lock); - } - } else { - WARN(1, "Indication 0x%04x lost\n", sig_wait->ind_id); - } - } else { - WARN_ON(fapi_get_u16(sig_wait->ind, receiver_pid) != sig_wait->process_id); - WARN_ON(fapi_get_u16(sig_wait->ind, id) != sig_wait->ind_id); - } - - sig_wait->ind_id = 0; - ind = sig_wait->ind; - sig_wait->ind = NULL; - - spin_unlock_bh(&sig_wait->send_signal_lock); - - return ind; -} - -/* mib_error: NULL when not required - * ind: 0 when not required, if used validate_cfm_wait_ind MUST be supplied - * validate_cfm_wait_ind: NULL when not required, if used ind MUS not be 0 - * NOTE: dev can be NULL! - */ -static struct sk_buff *slsi_mlme_tx_rx(struct slsi_dev *sdev, - struct net_device *dev, - struct sk_buff *skb, - u16 cfm_id, - struct sk_buff **mib_error, - u16 ind_id, - bool (*validate_cfm_wait_ind)(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm)) -{ - struct sk_buff *rx = NULL; - int err; - u16 req_id = fapi_get_u16(skb, id); - struct slsi_sig_send *sig_wait = &sdev->sig_wait; - - if (dev) { - struct netdev_vif *ndev_vif = netdev_priv(dev); - - sig_wait = &ndev_vif->sig_wait; - } - - if (sdev->mlme_blocked) { - SLSI_DBG3(sdev, SLSI_TX, "Rejected. mlme_blocked=%d", sdev->mlme_blocked); - slsi_kfree_skb(skb); - return NULL; - } - - slsi_wakelock(&sdev->wlan_wl); - SLSI_MUTEX_LOCK(sig_wait->mutex); - - spin_lock_bh(&sig_wait->send_signal_lock); - if (++sig_wait->process_id > SLSI_TX_PROCESS_ID_MAX) - sig_wait->process_id = SLSI_TX_PROCESS_ID_MIN; - - WARN_ON(sig_wait->cfm); - WARN_ON(sig_wait->ind); - slsi_kfree_skb(sig_wait->cfm); - slsi_kfree_skb(sig_wait->ind); - slsi_kfree_skb(sig_wait->mib_error); - sig_wait->cfm = NULL; - sig_wait->ind = NULL; - sig_wait->mib_error = NULL; - sig_wait->req_id = req_id; - sig_wait->cfm_id = cfm_id; - sig_wait->ind_id = ind_id; - - fapi_set_u16(skb, sender_pid, sig_wait->process_id); - spin_unlock_bh(&sig_wait->send_signal_lock); - - err = slsi_tx_control(sdev, dev, skb); - if (err != 0) { - SLSI_ERR(sdev, "Failed to send mlme signal:0x%.4X, err=%d\n", req_id, err); - slsi_kfree_skb(skb); - goto clean_exit; - } - - if (cfm_id) { - rx = slsi_mlme_wait_for_cfm(sdev, sig_wait); - if (rx && ind_id) { - /* The cfm skb is owned by the validate_cfm_wait_ind() function and MUST be freed or saved there */ - if (validate_cfm_wait_ind(sdev, dev, rx)) { - rx = slsi_mlme_wait_for_ind(sdev, dev, sig_wait, ind_id); - } else { - sig_wait->ind_id = 0; /* Reset as there is no wait for indication */ - rx = NULL; - } - } - } else if (ind_id) { - rx = slsi_mlme_wait_for_ind(sdev, dev, sig_wait, ind_id); - } - - /* The cfm_id and ind_id should ALWAYS be 0 at this point */ - WARN_ON(sig_wait->cfm_id); - WARN_ON(sig_wait->ind_id); - WARN_ON(sig_wait->cfm); - WARN_ON(sig_wait->ind); -clean_exit: - - spin_lock_bh(&sig_wait->send_signal_lock); - - sig_wait->req_id = 0; - sig_wait->cfm_id = 0; - sig_wait->ind_id = 0; - slsi_kfree_skb(sig_wait->cfm); - slsi_kfree_skb(sig_wait->ind); - sig_wait->cfm = NULL; - sig_wait->ind = NULL; - - if (mib_error) - *mib_error = sig_wait->mib_error; - else - slsi_kfree_skb(sig_wait->mib_error); - sig_wait->mib_error = NULL; - spin_unlock_bh(&sig_wait->send_signal_lock); - - SLSI_MUTEX_UNLOCK(sig_wait->mutex); - - slsi_wakeunlock(&sdev->wlan_wl); - return rx; -} - -/** - * NOTE: dev can be NULL! - */ -int slsi_mlme_req(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - int ret = 0; - struct slsi_sig_send *sig_wait = &sdev->sig_wait; - - if (dev) { - struct netdev_vif *ndev_vif = netdev_priv(dev); - - sig_wait = &ndev_vif->sig_wait; - } - spin_lock_bh(&sig_wait->send_signal_lock); - if (++sig_wait->process_id > SLSI_TX_PROCESS_ID_MAX) - sig_wait->process_id = SLSI_TX_PROCESS_ID_MIN; - fapi_set_u16(skb, sender_pid, sig_wait->process_id); - spin_unlock_bh(&sig_wait->send_signal_lock); - - ret = slsi_tx_control(sdev, dev, skb); - if (ret) - slsi_kfree_skb(skb); - return ret; -} - -struct sk_buff *slsi_mlme_req_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 ind_id) -{ - if (WARN_ON(!ind_id)) - goto err; - return slsi_mlme_tx_rx(sdev, dev, skb, 0, NULL, ind_id, NULL); -err: - slsi_kfree_skb(skb); - return NULL; -} - -struct sk_buff *slsi_mlme_req_no_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - return slsi_mlme_tx_rx(sdev, dev, skb, 0, NULL, 0, NULL); -} - -struct sk_buff *slsi_mlme_req_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id) -{ - if (WARN_ON(!cfm_id)) - goto err; - return slsi_mlme_tx_rx(sdev, dev, skb, cfm_id, NULL, 0, NULL); -err: - slsi_kfree_skb(skb); - return NULL; -} - -/* NOTE: dev can be NULL! */ -static inline struct sk_buff *slsi_mlme_req_cfm_mib(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id, struct sk_buff **mib_error) -{ - if (WARN_ON(!cfm_id)) - goto err; - if (WARN_ON(!mib_error)) - goto err; - return slsi_mlme_tx_rx(sdev, dev, skb, cfm_id, mib_error, 0, NULL); -err: - slsi_kfree_skb(skb); - return NULL; -} - -/* NOTE: dev can be NULL! */ -static inline struct sk_buff *slsi_mlme_req_cfm_ind(struct slsi_dev *sdev, - struct net_device *dev, - struct sk_buff *skb, - u16 cfm_id, - u16 ind_id, - bool (*validate_cfm_wait_ind)(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm)) -{ - if (WARN_ON(!cfm_id)) - goto err; - if (WARN_ON(!ind_id)) - goto err; - if (WARN_ON(!validate_cfm_wait_ind)) - goto err; - - return slsi_mlme_tx_rx(sdev, dev, skb, cfm_id, NULL, ind_id, validate_cfm_wait_ind); - -err: - slsi_kfree_skb(skb); - return NULL; -} - -static struct ieee80211_reg_rule *slsi_get_reg_rule(u32 center_freq, struct slsi_802_11d_reg_domain *domain_info) -{ - struct ieee80211_reg_rule *rule; - int i; - - for (i = 0; i < domain_info->regdomain->n_reg_rules; i++) { - rule = &domain_info->regdomain->reg_rules[i]; - - /* Consider 10Mhz on both side from the center frequency */ - if (((center_freq - MHZ_TO_KHZ(10)) >= rule->freq_range.start_freq_khz) && - ((center_freq + MHZ_TO_KHZ(10)) <= rule->freq_range.end_freq_khz)) - return rule; - } - - return NULL; -} - -u16 slsi_compute_chann_info(struct slsi_dev *sdev, u16 width, u16 center_freq0, u16 channel_freq) -{ - u16 chann_info; - u16 prim_chan_pos = 0; - - SLSI_DBG3(sdev, SLSI_MLME, "compute channel info\n"); - switch (width) { - case NL80211_CHAN_WIDTH_20: - chann_info = 20; - break; - case NL80211_CHAN_WIDTH_40: - chann_info = 40; - /* Check HT Minus */ - if (center_freq0 < channel_freq) - chann_info |= SLSI_CHANN_INFO_HT_SCB; - break; - case NL80211_CHAN_WIDTH_80: - /* F = { F1-30, ... F1+30 } => { 0x0000, ... 0x0300} */ - prim_chan_pos = ((30 + channel_freq - center_freq0) / 20); - if (prim_chan_pos > 3) { - SLSI_ERR(sdev, "Invalid center_freq0 in chandef : %u, primary channel = %u," - "primary chan pos calculated = %d\n", center_freq0, channel_freq, prim_chan_pos); - prim_chan_pos = 0; - } - prim_chan_pos = 0xFFFF & (prim_chan_pos << 8); - chann_info = 80 | prim_chan_pos; - break; - default: - SLSI_WARN(sdev, "Invalid chandef.width(0x%x)\n", width); - chann_info = 0; - break; - } - - SLSI_DBG3(sdev, SLSI_MLME, "channel_width:%u, chann_info:0x%x\n", width, chann_info); - return chann_info; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -u16 slsi_get_chann_info(struct slsi_dev *sdev, struct cfg80211_chan_def *chandef) -{ - u16 chann_info = 0; - - SLSI_UNUSED_PARAMETER(sdev); - - if (chandef->width == NL80211_CHAN_WIDTH_20 || chandef->width == NL80211_CHAN_WIDTH_20_NOHT) { - chann_info = 20; - SLSI_DBG3(sdev, SLSI_MLME, "channel_width:%u, chann_info:0x%x\n", chandef->width, chann_info); - } else if (chandef->chan) { - chann_info = slsi_compute_chann_info(sdev, chandef->width, chandef->center_freq1, - chandef->chan->center_freq); - } - return chann_info; -} - -int slsi_check_channelization(struct slsi_dev *sdev, struct cfg80211_chan_def *chandef, - int wifi_sharing_channel_switched) -{ - u8 width; - struct ieee80211_reg_rule *rule = NULL; - struct ieee80211_channel *channel = NULL; - u32 ref_flags; - - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20: - case NL80211_CHAN_WIDTH_20_NOHT: - width = 20; - break; - case NL80211_CHAN_WIDTH_40: - width = 40; - break; - case NL80211_CHAN_WIDTH_80: - width = 80; - break; - default: - SLSI_ERR(sdev, "Invalid chandef.width(0x%x)\n", chandef->width); - return -EINVAL; - } - - channel = ieee80211_get_channel(sdev->wiphy, chandef->chan->center_freq); - if (!channel) { - SLSI_ERR(sdev, "Invalid channel %d used to start AP. Channel not found\n", chandef->chan->center_freq); - return -EINVAL; - } - - if (wifi_sharing_channel_switched == 1) { - ref_flags = IEEE80211_CHAN_DISABLED -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13) - | IEEE80211_CHAN_PASSIVE_SCAN -#endif - ; - } else { - ref_flags = IEEE80211_CHAN_DISABLED | - IEEE80211_CHAN_RADAR -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13) - | IEEE80211_CHAN_PASSIVE_SCAN -#endif - ; - } - - if (channel->flags & ref_flags) { - SLSI_ERR(sdev, "Invalid channel %d used to start AP\n", chandef->chan->center_freq); - return -EINVAL; - } - rule = slsi_get_reg_rule(MHZ_TO_KHZ(chandef->center_freq1), &sdev->device_config.domain_info); - if (!rule) { - SLSI_ERR(sdev, "Invalid channel %d used to start AP. No reg rule found for this channel\n", chandef->chan->center_freq); - return -EINVAL; - } - - if (MHZ_TO_KHZ(width) <= rule->freq_range.max_bandwidth_khz) { - u32 width_boundary1, width_boundary2; - - width_boundary1 = MHZ_TO_KHZ(chandef->center_freq1 - width / 2); - width_boundary2 = MHZ_TO_KHZ(chandef->center_freq1 + width / 2); - if ((width_boundary1 >= rule->freq_range.start_freq_khz) && (width_boundary2 <= rule->freq_range.end_freq_khz)) - return 0; - SLSI_ERR(sdev, "Invalid channel %d used to start AP. Channel not within frequency range of the reg rule\n", chandef->chan->center_freq); - return -EINVAL; - } - return -EINVAL; -} - -#else -u16 slsi_get_chann_info(struct slsi_dev *sdev, enum nl80211_channel_type channel_type) -{ - u16 chann_info; - - SLSI_UNUSED_PARAMETER(sdev); - - /* Channel Info - * bits 0 ~ 7 : Channel Width (5, 10, 20, 40) - * bit 8 : Set to 1 if primary channel is greater than secondary channel (HT Minus) - */ - switch (channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - chann_info = 20; - break; - case NL80211_CHAN_HT40MINUS: - chann_info = 40 | SLSI_CHANN_INFO_HT_SCB; - break; - case NL80211_CHAN_HT40PLUS: - chann_info = 40; - break; - default: - SLSI_WARN(sdev, "Unknown channel_type: %d\n", channel_type); - chann_info = 0; - break; - } - - SLSI_DBG3(sdev, SLSI_MLME, "channel_type:%d, chann_info:0x%x\n", channel_type, chann_info); - return chann_info; -} - -int slsi_check_channelization(struct slsi_dev *sdev, enum nl80211_channel_type channel_type) -{ - return 0; -} - -#endif - -/* Called in the case of MIB SET errors. - * Decode and print a MIB buffer to the log for debug purposes. - */ -static void mib_buffer_dump_to_log(struct slsi_dev *sdev, u8 *mib_buffer, unsigned int mib_buffer_len) -{ - size_t mib_decode_result; - size_t offset = 0; - struct slsi_mib_entry decoded_mib_value; - struct slsi_mib_data mibdata; - int error_out_len = mib_buffer_len * 3; - int error_out_pos = 0; - char *error_out; - - SLSI_UNUSED_PARAMETER(sdev); - - FUNC_ENTER(sdev); - SLSI_ERR(sdev, "MIB buffer length: %u. MIB Error (decoded):", mib_buffer_len); - - if (!mib_buffer) { - SLSI_ERR(sdev, "MIB buffer pointer is NULL - can not decode MIB keys\n"); - return; - } - error_out = kmalloc(error_out_len, GFP_KERNEL); - - while (offset < mib_buffer_len) { - error_out_pos = 0; - mibdata.data = &mib_buffer[offset]; - mibdata.dataLength = mib_buffer_len - offset; - - mib_decode_result = slsi_mib_decode(&mibdata, &decoded_mib_value); - if (!mib_decode_result) { - SLSI_ERR_HEX(sdev, mibdata.data, mibdata.dataLength, "slsi_mib_decode() Failed to Decode:\n"); - break; - } - - offset += mib_decode_result; - /* Time for some eye candy - output the decoded MIB key at error level in the log */ - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "%d", (int)(decoded_mib_value.psid)); - if (decoded_mib_value.index[0]) { - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, ".%d", (int)(decoded_mib_value.index[0])); - if (decoded_mib_value.index[1]) - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, ".%d", (int)(decoded_mib_value.index[1])); - } - - switch (decoded_mib_value.value.type) { - case SLSI_MIB_TYPE_BOOL: - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=%s\n", decoded_mib_value.value.u.boolValue ? "TRUE" : "FALSE"); - break; - case SLSI_MIB_TYPE_UINT: - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=%d\n", (int)decoded_mib_value.value.u.uintValue); - break; - case SLSI_MIB_TYPE_INT: - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=%d\n", (int)decoded_mib_value.value.u.intValue); - break; - case SLSI_MIB_TYPE_OCTET: - { - u32 i; - - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=["); - for (i = 0; i < decoded_mib_value.value.u.octetValue.dataLength; i++) - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "%.2X", (int)decoded_mib_value.value.u.octetValue.data[i]); - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "]\n"); - break; - } - default: - error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=Can not decode MIB key type\n"); - break; - } - - SLSI_INFO_NODEV("%s", error_out); - } - kfree(error_out); - FUNC_EXIT(sdev); -} - -int slsi_mlme_set_ip_address(struct slsi_dev *sdev, struct net_device *dev) -{ - struct sk_buff *req; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *cfm; - int r = 0; - u32 ipaddr; - u8 multicast_add[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_SET_IP_ADDRESS.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - req = fapi_alloc(mlme_set_ip_address_req, MLME_SET_IP_ADDRESS_REQ, ndev_vif->ifnum, sizeof(ndev_vif->ipaddress)); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_set_ip_address_req.ip_version, 4); - fapi_set_memcpy(req, u.mlme_set_ip_address_req.multicast_address, multicast_add); - - ipaddr = htonl(be32_to_cpu(ndev_vif->ipaddress)); - fapi_append_data(req, (const u8 *)(&ipaddr), sizeof(ipaddr)); - - SLSI_DBG2(sdev, SLSI_MLME, "slsi_mlme_set_ip_address(vif: %d, IP: %pI4)\n", ndev_vif->ifnum, &ndev_vif->ipaddress); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_IP_ADDRESS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_ip_address_cfm(result:0x%04x) ERROR\n", fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - -int slsi_mlme_set_ipv6_address(struct slsi_dev *sdev, struct net_device *dev) -{ - struct sk_buff *req; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *cfm; - int r = 0; - u8 solicited_node_addr[ETH_ALEN] = { 0x33, 0x33, 0xff, 0x00, 0x00, 0x00 }; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_SET_IP_ADDRESS.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - req = fapi_alloc(mlme_set_ip_address_req, MLME_SET_IP_ADDRESS_REQ, ndev_vif->ifnum, 16); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_set_ip_address_req.ip_version, 6); - - if (ndev_vif->sta.nd_offload_enabled == 1) { - slsi_spinlock_lock(&ndev_vif->ipv6addr_lock); - memcpy(&solicited_node_addr[3], &ndev_vif->ipv6address.s6_addr[13], 3); - slsi_spinlock_unlock(&ndev_vif->ipv6addr_lock); - - fapi_set_memcpy(req, u.mlme_set_ip_address_req.multicast_address, solicited_node_addr); - fapi_append_data(req, ndev_vif->ipv6address.s6_addr, 16); - SLSI_DBG2(sdev, SLSI_MLME, "mlme_set_ip_address_req(vif: %d, IP: %pI6)\n", ndev_vif->ifnum, - &ndev_vif->ipv6address); - } else { - u8 node_addr_nd_disable[16]; - - memset(&node_addr_nd_disable, 0, sizeof(node_addr_nd_disable)); - fapi_append_data(req, node_addr_nd_disable, 16); - SLSI_DBG2(sdev, SLSI_MLME, "mlme_set_ip_address_req(vif: %d, IP-setting ip address to all zeros)\n", - ndev_vif->ifnum); - } - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_IP_ADDRESS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_ip_address_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - return r; -} -#endif - -int slsi_mlme_set(struct slsi_dev *sdev, struct net_device *dev, u8 *mib, int mib_len) -{ - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 ifnum = 0; - - if (dev) { - struct netdev_vif *ndev_vif = netdev_priv(dev); - - ifnum = ndev_vif->ifnum; - } - - req = fapi_alloc(mlme_set_req, MLME_SET_REQ, ifnum, mib_len); - if (!req) - return -ENOMEM; - - fapi_append_data(req, mib, mib_len); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_datalen(cfm)) { - mib_buffer_dump_to_log(sdev, fapi_get_data(cfm), fapi_get_datalen(cfm)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - - return r; -} - -int slsi_mlme_get(struct slsi_dev *sdev, struct net_device *dev, u8 *mib, int mib_len, u8 *resp, - int resp_buf_len, int *resp_len) -{ - struct sk_buff *req; - struct sk_buff *err = NULL; - struct sk_buff *cfm; - int r = 0; - u16 ifnum = 0; - - *resp_len = 0; - - if (dev) { - struct netdev_vif *ndev_vif = netdev_priv(dev); - - ifnum = ndev_vif->ifnum; - } - req = fapi_alloc(mlme_get_req, MLME_GET_REQ, ifnum, mib_len); - if (!req) - return -ENOMEM; - fapi_append_data(req, mib, mib_len); - - cfm = slsi_mlme_req_cfm_mib(sdev, dev, req, MLME_GET_CFM, &err); - if (!cfm) - return -EIO; - - if (err) { - SLSI_DBG1(sdev, SLSI_MLME, "ERROR: mlme_get_cfm with mib error\n"); - mib_buffer_dump_to_log(sdev, fapi_get_data(err), fapi_get_datalen(err)); - LOG_CONDITIONALLY(fapi_get_datalen(cfm) > resp_buf_len, - SLSI_ERR(sdev, "Insufficient resp_buf_len(%d). mlme_get_cfm(%d)\n", - resp_buf_len, fapi_get_datalen(cfm))); - r = -EINVAL; - } - - /* if host has requested for multiple PSIDs in same request, we can get a - * combination of error and success - */ - if (fapi_get_datalen(cfm) <= resp_buf_len) { - *resp_len = fapi_get_datalen(cfm); - memcpy(resp, fapi_get_data(cfm), fapi_get_datalen(cfm)); - r = 0; - } else { - SLSI_WARN(sdev, "Insufficient length (%d) to read MIB values, expected =%d\n", resp_buf_len, fapi_get_datalen(cfm)); - r = -EINVAL; - } - - slsi_kfree_skb(err); - slsi_kfree_skb(cfm); - - return r; -} - -int slsi_mlme_add_vif(struct slsi_dev *sdev, struct net_device *dev, u8 *interface_address, u8 *device_address) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0, i; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_ADD_VIF.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - /* reset host stats */ - for (i = 0; i < SLSI_LLS_AC_MAX; i++) { - ndev_vif->tx_no_ack[i] = 0; - ndev_vif->tx_packets[i] = 0; - ndev_vif->rx_packets[i] = 0; - } - req = fapi_alloc(mlme_add_vif_req, MLME_ADD_VIF_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - fapi_set_u16(req, u.mlme_add_vif_req.virtual_interface_type, ndev_vif->vif_type); - fapi_set_memcpy(req, u.mlme_add_vif_req.interface_address, interface_address); - fapi_set_memcpy(req, u.mlme_add_vif_req.device_address, device_address); - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_add_vif_req(vif:%d)\n", ndev_vif->ifnum); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ADD_VIF_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_add_vif_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_add_vif_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_add_vif_cfm.result_code)); - r = -EINVAL; - } - - /* By default firmware vif will be in active mode */ - ndev_vif->power_mode = FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE; - - slsi_kfree_skb(cfm); - return r; -} - -void slsi_mlme_del_vif(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_DEL_VIF.request\n"); - return; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_del_vif_req(vif:%d)\n", ndev_vif->ifnum); - req = fapi_alloc(mlme_del_vif_req, MLME_DEL_VIF_REQ, ndev_vif->ifnum, 0); - if (!req) - return; - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_DEL_VIF_CFM); - if (!cfm) - return; - - if (fapi_get_u16(cfm, u.mlme_del_vif_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) - SLSI_NET_ERR(dev, "mlme_del_vif_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_del_vif_cfm.result_code)); - - if (((ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) || (ndev_vif->iftype == NL80211_IFTYPE_STATION)) && - (ndev_vif->delete_probe_req_ies)) { - kfree(ndev_vif->probe_req_ies); - ndev_vif->probe_req_ies = NULL; - ndev_vif->probe_req_ie_len = 0; - ndev_vif->delete_probe_req_ies = false; - } - if (SLSI_IS_VIF_INDEX_P2P(ndev_vif)) - ndev_vif->drv_in_p2p_procedure = false; - - slsi_kfree_skb(cfm); -} - -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -int slsi_mlme_set_forward_beacon(struct slsi_dev *sdev, struct net_device *dev, int action) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "wlanlite does not support mlme_forward_bacon_req\n"); - return -EOPNOTSUPP; - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_forward_beacon_req(action = %s(%d))\n", action ? "start" : "stop", action); - - req = fapi_alloc(mlme_forward_beacon_req, MLME_FORWARD_BEACON_REQ, ndev_vif->ifnum, 0); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc for mlme_forward_beacon_req is failed\n"); - return -ENOMEM; - } - - fapi_set_u16(req, u.mlme_forward_beacon_req.wips_action, action); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_FORWARD_BEACON_CFM); - if (!cfm) { - SLSI_NET_ERR(dev, "receiving mlme_forward_beacon_cfm is failed\n"); - return -EIO; - } - - if (fapi_get_u16(cfm, u.mlme_forward_beacon_cfm.result_code) != FAPI_RESULTCODE_HOST_REQUEST_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_forward_beacon_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_forward_beacon_cfm.result_code)); - return -EINVAL; - } - - ndev_vif->is_wips_running = (action ? true : false); - - slsi_kfree_skb(cfm); - return 0; -} -#endif - -int slsi_mlme_set_channel(struct slsi_dev *sdev, struct net_device *dev, struct ieee80211_channel *chan, u16 duration, u16 interval, u16 count) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "wlanlite does not support MLME_SET_CHANNEL.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_channel_req(freq:%u, duration:%u, interval:%u, count:%u)\n", chan->center_freq, duration, interval, count); - - req = fapi_alloc(mlme_set_channel_req, MLME_SET_CHANNEL_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_set_channel_req.availability_duration, duration); - fapi_set_u16(req, u.mlme_set_channel_req.availability_interval, interval); - fapi_set_u16(req, u.mlme_set_channel_req.count, count); - fapi_set_u16(req, u.mlme_set_channel_req.channel_frequency, SLSI_FREQ_HOST_TO_FW(chan->center_freq)); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CHANNEL_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_channel_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_channel_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_channel_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_unset_channel_req(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "slsi_mlme_unset_channel_req\n"); - - req = fapi_alloc(mlme_unset_channel_req, MLME_UNSET_CHANNEL_REQ, ndev_vif->ifnum, 0); - - if (!req) - return -ENOMEM; - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_UNSET_CHANNEL_CFM); - - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_unset_channel_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_unset_channel_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_unset_channel_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -void slsi_ap_obss_scan_done_ind(struct net_device *dev, struct netdev_vif *ndev_vif) -{ - struct sk_buff *scan_res; - u16 scan_id = SLSI_SCAN_HW_ID; - - SLSI_UNUSED_PARAMETER(dev); - - SLSI_NET_DBG1(dev, SLSI_MLME, "Scan before AP start completed\n"); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex)); - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - - scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], NULL); - while (scan_res) { - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(scan_res); - size_t mgmt_len = fapi_get_mgmtlen(scan_res); - size_t ie_len = mgmt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); /* ieee80211_mgmt structure is similar for Probe Response and Beacons */ - - SLSI_NET_DBG4(dev, SLSI_MLME, "OBSS scan result (scan_id:%d, %pM, freq:%d, rssi:%d, ie_len = %zu)\n", - fapi_get_u16(scan_res, u.mlme_scan_ind.scan_id), - fapi_get_mgmt(scan_res)->bssid, - fapi_get_u16(scan_res, u.mlme_scan_ind.channel_frequency) / 2, - fapi_get_s16(scan_res, u.mlme_scan_ind.rssi), - ie_len); - - if (!cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable, ie_len)) { - SLSI_NET_DBG1(dev, SLSI_MLME, "Non HT BSS detected on primary channel\n"); - ndev_vif->ap.non_ht_bss_present = true; - } - - slsi_kfree_skb(scan_res); - scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], NULL); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); -} - -/* Null check for cfm done in caller function */ -static bool slsi_scan_cfm_validate(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm) -{ - bool r = true; - - if (fapi_get_u16(cfm, u.mlme_add_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_ERR_NODEV("mlme_add_scan_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_add_scan_cfm.result_code)); - r = false; - } - - slsi_kfree_skb(cfm); - return r; -} - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE -int slsi_mlme_append_gscan_channel_list(struct slsi_dev *sdev, - struct net_device *dev, - struct sk_buff *req, - struct slsi_nl_bucket_param *nl_bucket) -{ - u16 channel_freq; - u8 i; - u8 *p; - const u8 channels_list_ie_header[] = { - 0xDD, /* Element ID: Vendor Specific */ - 0x05, /* Length: actual length will be updated later */ - 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */ - 0x01, /* OUI Type: Scan parameters */ - 0x02 /* OUI Subtype: channel list */ - }; - u8 *channels_list_ie = fapi_append_data(req, channels_list_ie_header, sizeof(channels_list_ie_header)); - - if (!channels_list_ie) { - SLSI_WARN(sdev, "channel list IE append failed\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - - if (nl_bucket->band == WIFI_BAND_UNSPECIFIED) - /* channel list is added only if band is UNSPECIFIED */ - for (i = 0; i < nl_bucket->num_channels; i++) { - p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE); - if (!p) { - SLSI_ERR(sdev, "chan desc[%d] append failed\n", i); - slsi_kfree_skb(req); - return -EINVAL; - } - channel_freq = SLSI_FREQ_HOST_TO_FW(nl_bucket->channels[i].channel); - channel_freq = cpu_to_le16(channel_freq); - memcpy(p, &channel_freq, sizeof(channel_freq)); - p[2] = FAPI_SCANPOLICY_ANY_RA; - channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE; /* Length */ - } - else { - p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE); - if (!p) { - SLSI_ERR(sdev, "chan desc(band specific)append failed\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - /* Channel frequency set to 0 for all channels allowed by the corresponding regulatory domain and scan policy */ - channel_freq = 0; - memcpy(p, &channel_freq, sizeof(channel_freq)); - p[2] = slsi_gscan_get_scan_policy(nl_bucket->band); - channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE; - } - - return 0; -} -#endif - -static int slsi_mlme_append_channel_list(struct slsi_dev *sdev, - struct net_device *dev, - struct sk_buff *req, - u32 num_channels, - struct ieee80211_channel *channels[], - u16 scan_type, - bool passive_scan) -{ - int chann; - u16 freq_fw_unit; - u8 i; - int n_valid_channels = 0; - u8 *p; - - const u8 channels_list_ie_header[] = { - 0xDD, /* Element ID: vendor specific */ - 0x05, /* Length: actual length will be updated later */ - 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */ - 0x01, /* OUI Type: scan parameters */ - 0x02 /* OUI Subtype: channel list */ - }; - - u8 *channels_list_ie = fapi_append_data(req, channels_list_ie_header, sizeof(channels_list_ie_header)); - - if (!channels_list_ie) { - SLSI_WARN(sdev, "channel list IE append failed\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - - /* For P2P Full Scan, Setting Channel Frequency = 0x0000, Scan Policy = 2.4GHz, 5GHz and Non-Dfs. */ - if (scan_type == FAPI_SCANTYPE_P2P_SCAN_FULL) { - p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE); - if (!p) { - SLSI_WARN(sdev, "scan channel descriptor append failed\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - p[0] = 0; - p[1] = 0; - p[2] = FAPI_SCANPOLICY_2_4GHZ | FAPI_SCANPOLICY_5GHZ | FAPI_SCANPOLICY_NON_DFS; - channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE; - return 0; - } - - for (i = 0; i < num_channels; i++) { - chann = channels[i]->hw_value & 0xFF; - - if (sdev->device_config.supported_band) { - if (channels[i]->band == NL80211_BAND_2GHZ && sdev->device_config.supported_band != SLSI_FREQ_BAND_2GHZ) - continue; - if (channels[i]->band == NL80211_BAND_5GHZ && sdev->device_config.supported_band != SLSI_FREQ_BAND_5GHZ) - continue; - } - - n_valid_channels++; - p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE); - if (!p) { - SLSI_WARN(sdev, "scan channel descriptor append failed\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - freq_fw_unit = 2 * ieee80211_channel_to_frequency(chann, (chann <= 14) ? - NL80211_BAND_2GHZ : NL80211_BAND_5GHZ); - freq_fw_unit = cpu_to_le16(freq_fw_unit); - memcpy(p, &freq_fw_unit, sizeof(freq_fw_unit)); - - if (passive_scan && (scan_type != FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION)) - p[2] = FAPI_SCANPOLICY_PASSIVE; - else - p[2] = 0; - - channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE; - } - if (n_valid_channels == 0) { - SLSI_NET_ERR(dev, "no valid channels to Scan\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - return 0; -} - -static inline int slsi_set_scan_params( - struct net_device *dev, - u16 scan_id, - u16 scan_type, - u16 report_mode, - int num_ssids, - struct cfg80211_ssid *ssids, - struct sk_buff *req) -{ - u8 *p = NULL; - u8 i; - struct cfg80211_ssid *pssid = ssids; -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct slsi_dev *sdev = netdev_vif->sdev; -#endif - - fapi_set_u16(req, u.mlme_add_scan_req.scan_id, scan_id); - fapi_set_u16(req, u.mlme_add_scan_req.scan_type, scan_type); - fapi_set_u16(req, u.mlme_add_scan_req.report_mode_bitmap, report_mode); - - -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - if (sdev->scan_addr_set) - fapi_set_memcpy(req, u.mlme_add_scan_req.device_address, sdev->scan_mac_addr); - else -#endif - fapi_set_memcpy(req, u.mlme_add_scan_req.device_address, dev->dev_addr); - - for (i = 0; i < num_ssids; i++, pssid++) { - p = fapi_append_data(req, NULL, 2 + pssid->ssid_len); - if (!p) { - slsi_kfree_skb(req); - SLSI_NET_WARN(dev, "fail to append SSID element to scan request\n"); - return -EINVAL; - } - - *p++ = WLAN_EID_SSID; - *p++ = pssid->ssid_len; - - if (pssid->ssid_len) - memcpy(p, pssid->ssid, pssid->ssid_len); - } - return 0; -} - -#define SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM 7 -int slsi_mlme_add_sched_scan(struct slsi_dev *sdev, - struct net_device *dev, - struct cfg80211_sched_scan_request *request, - const u8 *ies, - u16 ies_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - size_t alloc_data_size = 0; - u32 i, j; - u32 num_ssid_filter_elements = 0; - - /* Scan Timing IE: default values */ - u8 scan_timing_ie[] = { - 0xdd, /* Element ID: Vendor Specific */ - 0x11, /* Length */ - 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */ - 0x01, /* OUI Type: Scan parameters */ - 0x01, /* OUI Subtype: Scan timing */ - 0x00, 0x00, 0x00, 0x00, /* Min_Period: filled later in the function */ - 0x00, 0x00, 0x00, 0x00, /* Max_Period: filled later in the function */ - 0x01, /* Exponent */ - 0x01, /* Step count */ - 0x00, 0x01 /* Skip first period: true for scheduled scans*/ - }; - - u8 ssid_filter_ie_hdr[] = { - 0xdd, /* Element ID: Vendor Specific */ - 0x05, /* Length */ - 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */ - 0x01, /* OUI Type: Scan parameters */ - 0x04 /* OUI Subtype: SSID Filter */ - }; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_WARN(dev, "not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - - if (WARN_ON(!(dev->dev_addr))) - return -EINVAL; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex)); - -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) - if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { - if (sdev->fw_mac_randomization_enabled) { - memcpy(sdev->scan_mac_addr, request->mac_addr, ETH_ALEN); - r = slsi_set_mac_randomisation_mask(sdev, request->mac_addr_mask); - if (!r) - sdev->scan_addr_set = 1; - } else { - SLSI_NET_INFO(dev, "Mac Randomization is not enabled in Firmware\n"); - sdev->scan_addr_set = 0; - } - } -#endif -#endif - - alloc_data_size += sizeof(scan_timing_ie) + ies_len + SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN + - (request->n_channels * SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE); - - for (i = 0; i < request->n_ssids; i++) { - /* 2 bytes for SSID EID and length field + variable length SSID */ - alloc_data_size += (2 + request->ssids[i].ssid_len); - } - - if (request->n_match_sets) { - num_ssid_filter_elements = (request->n_match_sets / SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM) + 1; - /* EID(1) + len(1) + oui(3) + type/subtype(2) + 7 ssid descriptors(7 * 33) */ - alloc_data_size += 238 * num_ssid_filter_elements; - } - - req = fapi_alloc(mlme_add_scan_req, MLME_ADD_SCAN_REQ, 0, alloc_data_size); - if (!req) - return -ENOMEM; - - r = slsi_set_scan_params(dev, (ndev_vif->ifnum << 8 | SLSI_SCAN_SCHED_ID), - FAPI_SCANTYPE_SCHEDULED_SCAN, - FAPI_REPORTMODE_REAL_TIME, - request->n_ssids, - request->ssids, - req); - if (r) - return r; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) - SLSI_U32_TO_BUFF_LE(request->scan_plans->interval * 1000 * 1000, &scan_timing_ie[7]); - SLSI_U32_TO_BUFF_LE(request->scan_plans->interval * 1000 * 1000, &scan_timing_ie[11]); -#else - SLSI_U32_TO_BUFF_LE(request->interval * 1000, &scan_timing_ie[7]); - SLSI_U32_TO_BUFF_LE(request->interval * 1000, &scan_timing_ie[11]); -#endif - - fapi_append_data(req, scan_timing_ie, sizeof(scan_timing_ie)); - fapi_append_data(req, ies, ies_len); - - if (request->n_match_sets) { - struct cfg80211_match_set *match_sets = request->match_sets; - u8 *ssid_filter_ie; - - for (j = 0; j < num_ssid_filter_elements; j++) { - ssid_filter_ie = fapi_append_data(req, ssid_filter_ie_hdr, sizeof(ssid_filter_ie_hdr)); - if (!ssid_filter_ie) { - slsi_kfree_skb(req); - SLSI_ERR(sdev, "ssid_filter_ie append failed\n"); - return -EIO; - } - for (i = 0; i < SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM; i++, match_sets++) { - if ((j * SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM) + i >= request->n_match_sets) - break; - SLSI_NET_DBG2(dev, SLSI_MLME, "SSID: %.*s", - match_sets->ssid.ssid_len, match_sets->ssid.ssid); - ssid_filter_ie[1] += (1 + match_sets->ssid.ssid_len); - fapi_append_data(req, &match_sets->ssid.ssid_len, 1); - fapi_append_data(req, match_sets->ssid.ssid, match_sets->ssid.ssid_len); - } - } - } - - if (request->n_channels) { - r = slsi_mlme_append_channel_list(sdev, dev, req, request->n_channels, request->channels, - FAPI_SCANTYPE_SCHEDULED_SCAN, request->n_ssids == 0); - if (r) - return r; - } - - rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_ADD_SCAN_CFM); - if (!rx) - return -EIO; - - if (fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_add_scan_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(rx); - return r; -} - -int slsi_mlme_add_scan( - struct slsi_dev *sdev, - struct net_device *dev, - u16 scan_type, - u16 report_mode, - u32 n_ssids, - struct cfg80211_ssid *ssids, - u32 n_channels, - struct ieee80211_channel *channels[], - void *gscan, - const u8 *ies, - u16 ies_len, - bool wait_for_ind) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - size_t alloc_data_size = 0; - u32 i; - - /* Scan Timing IE: default values */ - u8 scan_timing_ie[] = { - 0xdd, /* Element ID: Vendor Specific */ - 0x11, /* Length */ - 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */ - 0x01, /* OUI Type: Scan parameters */ - 0x01, /* OUI Subtype: Scan timing */ - 0x00, 0x00, 0x00, 0x00, /* Min_Period: filled later in the function */ - 0x00, 0x00, 0x00, 0x00, /* Max_Period: filled later in the function */ - 0x00, /* Exponent */ - 0x00, /* Step count */ - 0x00, 0x00 /* Skip first period: false */ - }; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_WARN(dev, "not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - - if (WARN_ON(!(dev->dev_addr))) - return -EINVAL; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex)); - SLSI_INFO(sdev, "scan started for id:0x%x, n_channels:%d, n_ssids:%d, scan_type:%d\n", - (ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID), n_channels, n_ssids, scan_type); - - alloc_data_size += sizeof(scan_timing_ie) + - ies_len + - (SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN + (n_channels * SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE)); - - for (i = 0; i < n_ssids; i++) - alloc_data_size += 2 + ssids[i].ssid_len; /* 2: SSID EID + len */ - - req = fapi_alloc(mlme_add_scan_req, MLME_ADD_SCAN_REQ, 0, alloc_data_size); - if (!req) - return -ENOMEM; - - if (!gscan) { - r = slsi_set_scan_params( - dev, - (ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID), - scan_type, - report_mode, - n_ssids, - ssids, - req); - if (r) - return r; - - fapi_append_data(req, scan_timing_ie, sizeof(scan_timing_ie)); - fapi_append_data(req, ies, ies_len); - - if (n_channels) { - r = slsi_mlme_append_channel_list(sdev, dev, req, n_channels, channels, scan_type, - n_ssids == 0); - if (r) - return r; - } - } -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - else { - struct slsi_gscan_param *gscan_param = (struct slsi_gscan_param *)gscan; - - r = slsi_set_scan_params( - dev, - gscan_param->bucket->scan_id, - scan_type, - report_mode, - n_ssids, - ssids, - req); - if (r) - return r; - - SLSI_U32_TO_BUFF_LE((gscan_param->nl_bucket->period * 1000), &scan_timing_ie[7]); - if (gscan_param->nl_bucket->exponent) { - SLSI_U32_TO_BUFF_LE((gscan_param->nl_bucket->max_period * 1000), &scan_timing_ie[11]); - scan_timing_ie[15] = (u8)gscan_param->nl_bucket->exponent; - scan_timing_ie[16] = (u8)gscan_param->nl_bucket->step_count; - } - fapi_append_data(req, scan_timing_ie, sizeof(scan_timing_ie)); - - r = slsi_mlme_append_gscan_channel_list(sdev, dev, req, gscan_param->nl_bucket); - if (r) - return r; - } -#endif - if (wait_for_ind) { - /* Use the Global sig_wait not the Interface specific for Scan Req */ - rx = slsi_mlme_req_cfm_ind(sdev, NULL, req, MLME_ADD_SCAN_CFM, MLME_SCAN_DONE_IND, slsi_scan_cfm_validate); - if (!rx) - return -EIO; - SLSI_NET_DBG3(dev, SLSI_MLME, "mlme_scan_done_ind()\n"); - - /* slsi_mlme_add_scan is a generic definition for multiple handlers - * Any added functionality, if not generic, should not be defined here. - * It should be a part of calling function. - */ - } else { - /* Use the Global sig_wait not the Interface specific for Scan Req */ - rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_ADD_SCAN_CFM); - if (!rx) - return -EIO; - if (fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_add_scan_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code)); - r = -EINVAL; - } - } - slsi_kfree_skb(rx); - return r; -} - -int slsi_mlme_del_scan(struct slsi_dev *sdev, struct net_device *dev, u16 scan_id, bool scan_timed_out) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_WARN(dev, "not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_del_scan_req(scan_id:%d)\n", scan_id); - - if ((scan_id & 0xFF) == SLSI_SCAN_HW_ID && ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req && !scan_timed_out) - cancel_delayed_work(&ndev_vif->scan_timeout_work); - - req = fapi_alloc(mlme_del_scan_req, MLME_DEL_SCAN_REQ, 0, 0); - if (!req) - return -ENOMEM; - fapi_set_u16(req, u.mlme_del_scan_req.scan_id, scan_id); - - /* Use the Global sig_wait not the Interface specific for Scan Req */ - cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_DEL_SCAN_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_del_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_del_scan_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_del_scan_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -static void slsi_ap_add_ext_capab_ie(struct sk_buff *req, struct netdev_vif *ndev_vif, const u8 *prev_ext) -{ - u8 ext_capa_ie[SLSI_AP_EXT_CAPAB_IE_LEN_MAX]; - int i; - int prev_len = 0; - - ext_capa_ie[0] = WLAN_EID_EXT_CAPABILITY; - ext_capa_ie[1] = SLSI_AP_EXT_CAPAB_IE_LEN_MAX - 1 - 1; - if (prev_ext) { - prev_len = prev_ext[1]; - for (i = 2; i < prev_len + 2; i++) - ext_capa_ie[i] = prev_ext[i]; - } - for (i = prev_len + 2; i < SLSI_AP_EXT_CAPAB_IE_LEN_MAX; i++) - ext_capa_ie[i] = 0x00; - SLSI_DBG3(ndev_vif->sdev, SLSI_MLME, "New Ext capab Added\n"); - /* For VHT, set the Operating Mode Notification field - Bit 62 (8th Octet) */ - ext_capa_ie[9] |= 0x40; - - fapi_append_data(req, &ext_capa_ie[0], SLSI_AP_EXT_CAPAB_IE_LEN_MAX); -} -#endif - -static int slsi_prepare_country_ie(struct slsi_dev *sdev, u16 center_freq, u8 *country_ie, u8 **new_country_ie) -{ - struct ieee80211_supported_band band; - struct ieee80211_reg_rule *rule; - struct ieee80211_channel *channels; - u8 *ie; - u8 offset = 0; - int i; - - /* Select frequency band */ - if (center_freq < 5180) - band = slsi_band_2ghz; - else - band = slsi_band_5ghz; - - /* Allocate memory for the new country IE - EID(1) + Len(1) + CountryString(3) + ChannelInfo (n * 3) */ - ie = kmalloc(5 + (band.n_channels * 3), GFP_KERNEL); - if (!ie) { - SLSI_ERR(sdev, "Failed to allocate memory\n"); - return -ENOMEM; - } - - /* Preapre the new country IE */ - ie[offset++] = country_ie[0]; /* Element IE */ - ie[offset++] = 0; /* IE Length - initialized at the end of this function */ - ie[offset++] = sdev->device_config.domain_info.regdomain->alpha2[0]; /* Country code */ - ie[offset++] = sdev->device_config.domain_info.regdomain->alpha2[1]; /* Country code */ - ie[offset++] = country_ie[4]; /* CountryString: 3rd octet */ - - channels = band.channels; - for (i = 0; i < band.n_channels; i++, channels++) { - /* Get the regulatory rule for the channel */ - rule = slsi_get_reg_rule(MHZ_TO_KHZ(channels->center_freq), &sdev->device_config.domain_info); - if (rule) { - ie[offset++] = channels->hw_value; /* Channel number */ - ie[offset++] = 1; /* Number of channels */ - ie[offset++] = MBM_TO_DBM(rule->power_rule.max_eirp); /* Max TX power */ - } - } - - ie[1] = offset - 2; /* Length of IE */ - *new_country_ie = ie; - - return 0; -} - -int slsi_modify_ies(struct net_device *dev, u8 eid, u8 *ies, int ies_len, u8 ie_index, u8 ie_value) -{ - u8 *ie; - - SLSI_NET_DBG1(dev, SLSI_MLME, "eid: %d, ie_value = 0x%x\n", eid, ie_value); - - ie = (u8 *)cfg80211_find_ie(eid, ies, ies_len); - if (ie) { - switch (eid) { - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_VHT_CAPABILITY: - ie[ie_index] |= ie_value; - break; - case WLAN_EID_DS_PARAMS: - case WLAN_EID_HT_OPERATION: - if (ie_index == 2) - ie[ie_index] = ie_value; - else - ie[ie_index] |= ie_value; - break; - default: - SLSI_NET_WARN(dev, "slsi_modify_ies: IE type mismatch : %d\n", eid); - return false; - } - return true; - } - SLSI_NET_WARN(dev, "slsi_modify_ies: IE not found : %d\n", eid); - return false; -} - -static void slsi_mlme_start_prepare_ies(struct sk_buff *req, struct netdev_vif *ndev_vif, struct cfg80211_ap_settings *settings, const u8 *wpa_ie_pos, const u8 *wmm_ie_pos) -{ - const u8 *wps_ie, *vht_capab_ie, *tail_pos = NULL, *ext_capab_ie; - size_t beacon_ie_len = 0, tail_length = 0; - u8 *country_ie; - const u8 *beacon_tail = settings->beacon.tail; - size_t beacon_tail_len = settings->beacon.tail_len; - - /** - * Channel list of Country IE prepared by hostapd is wrong, so driver needs remove the existing country IE and prepare correct one. - * Hostapd adds country IE at the beginning of the tail, beacon_tail is moved to the next IE to avoid the default county IE. - */ - country_ie = (u8 *)cfg80211_find_ie(WLAN_EID_COUNTRY, beacon_tail, beacon_tail_len); - if (country_ie) { - u8 *new_country_ie = NULL; - - SLSI_DBG3(ndev_vif->sdev, SLSI_MLME, "Country IE found, length = %d", country_ie[1]); - - /* Prepare the new country IE */ - if (slsi_prepare_country_ie(ndev_vif->sdev, ndev_vif->chan->center_freq, country_ie, &new_country_ie) != 0) - SLSI_ERR(ndev_vif->sdev, "Failed to prepare country IE"); - - /* Add the new country IE */ - if (new_country_ie) { - /* new_country_ie[1] ontains the length of IE */ - fapi_append_data(req, new_country_ie, (new_country_ie[1] + 2)); - - /* Free the memory allocated for the new country IE */ - kfree(new_country_ie); - - /* Remove the default country IE from the beacon_tail */ - beacon_tail += (country_ie[1] + 2); - beacon_tail_len -= (country_ie[1] + 2); - } - } - - /* Modify HT IE based on OBSS scan data */ - if (ndev_vif->ap.non_ht_bss_present) { - u8 op_mode = 1; - - SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_MLME, "Modify Operating mode of BSS in HT IE\n"); - slsi_modify_ies(ndev_vif->wdev.netdev, WLAN_EID_HT_OPERATION, (u8 *)settings->beacon.tail, settings->beacon.tail_len, 4, op_mode); - ndev_vif->ap.non_ht_bss_present = false; - } - - /* Vendor IEs are excluded from start_req. Currently WPA IE, WMM IE, WPS IE and P2P IE need to be excluded. - * From hostapd, order of IEs are - WPA, WMM, WPS and P2P - * Of these the WMM, WPS and P2P IE are usually at the end. - * Note: There can be "eid_p2p_manage" and "eid_hs20" after WPS and P2P IE. Both of these are currently not supported. - */ - - /* Exclude WMM or WPS IE */ - if (wmm_ie_pos) /* WMM IE is present. Remove from this position onwards, i.e. copy only till this data. WPS and P2P IE will also get removed. */ - beacon_ie_len = wmm_ie_pos - beacon_tail; - else { - /* WMM IE is not present. Check for WPS IE (and thereby P2P IE) and exclude it */ - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, beacon_tail, beacon_tail_len); - if (wps_ie) - beacon_ie_len = wps_ie - beacon_tail; - else - beacon_ie_len = beacon_tail_len; - } - - /* Exclude WPA IE if present */ - if (wpa_ie_pos) { - size_t len_before, len; - - len_before = wpa_ie_pos - beacon_tail; - fapi_append_data(req, beacon_tail, len_before); - - len = len_before + ndev_vif->ap.wpa_ie_len; - - if (beacon_ie_len > len) { /* More IEs to go */ - tail_length = beacon_ie_len - len; - tail_pos = (beacon_tail + len); - } else /* No more IEs, don't add Ext Capab IE as no HT/VHT */ - return; - } else { - tail_length = beacon_ie_len; - tail_pos = beacon_tail; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - /* Add Ext Capab IE only for VHT mode for now */ - if (ndev_vif->chandef->width == NL80211_CHAN_WIDTH_80) { - /* Ext Capab should be before VHT IEs */ - vht_capab_ie = (cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, tail_pos, tail_length)); - ext_capab_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, tail_pos, tail_length); - while (tail_length > 2) { - if (tail_pos[0] == WLAN_EID_VHT_CAPABILITY) - slsi_ap_add_ext_capab_ie(req, ndev_vif, ext_capab_ie); - else if (tail_pos[0] != WLAN_EID_EXT_CAPABILITY && tail_pos[0] != WLAN_EID_VHT_OPERATION) - fapi_append_data(req, tail_pos, tail_pos[1] + 2); - - tail_length -= tail_pos[1] + 2; - tail_pos += tail_pos[1] + 2; - } - if (!vht_capab_ie) - slsi_ap_add_ext_capab_ie(req, ndev_vif, ext_capab_ie); - } else { - fapi_append_data(req, tail_pos, tail_length); - } -#else - fapi_append_data(req, tail_pos, tail_length); -#endif -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -/*EID + LEN + CAPABILITIES + MCS */ -/* 1+1+4+8 */ -#define SLSI_VHT_CAPABILITIES_IE_LEN 14 - -/* EID + LEN + WIDTH + SEG0 + SEG1 + MCS */ -/* 1+1+1+1+1+2 */ -#define SLSI_VHT_OPERATION_IE_LEN 7 - -static int slsi_prepare_vht_ies(struct net_device *dev, u8 **vht_ie_capab, u8 **vht_ie_operation) -{ - u32 capabs; - u16 mcs; - u8 *p_cap, *p_oper; - struct netdev_vif *ndev_vif = netdev_priv(dev); - - *vht_ie_capab = kmalloc(SLSI_VHT_CAPABILITIES_IE_LEN, GFP_KERNEL); - if (!(*vht_ie_capab)) - return -EINVAL; - *vht_ie_operation = kmalloc(SLSI_VHT_OPERATION_IE_LEN, GFP_KERNEL); - if (!(*vht_ie_operation)) { - kfree(*vht_ie_capab); - return -EINVAL; - } - - p_cap = *vht_ie_capab; - p_oper = *vht_ie_operation; - - *p_cap++ = WLAN_EID_VHT_CAPABILITY; - *p_cap++ = SLSI_VHT_CAPABILITIES_IE_LEN - 1 - 1; - capabs = cpu_to_le32(slsi_vht_cap.cap); - memcpy(p_cap, &capabs, sizeof(capabs)); - p_cap += sizeof(capabs); - memcpy(p_cap, &slsi_vht_cap.vht_mcs, sizeof(slsi_vht_cap.vht_mcs)); - - *p_oper++ = WLAN_EID_VHT_OPERATION; - *p_oper++ = SLSI_VHT_OPERATION_IE_LEN - 1 - 1; - *p_oper++ = IEEE80211_VHT_CHANWIDTH_80MHZ; - *p_oper++ = ieee80211_frequency_to_channel(ndev_vif->chandef->center_freq1); - *p_oper++ = 0; - mcs = cpu_to_le16(0xfffc); - memcpy(p_oper, &mcs, sizeof(mcs)); - - return 0; -} -#endif - -int slsi_mlme_start(struct slsi_dev *sdev, struct net_device *dev, u8 *bssid, struct cfg80211_ap_settings *settings, const u8 *wpa_ie_pos, const u8 *wmm_ie_pos, bool append_vht_ies) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - struct ieee80211_mgmt *mgmt; - int r = 0; - u8 *p; - enum nl80211_auth_type auth_type = settings->auth_type; - u16 beacon_ie_head_len; - u16 chan_info; - u16 fw_freq; - u16 vht_ies_len = 0; - u8 ext_capab_len = 0; - const u8 *recv_vht_capab_ie, *recv_vht_operation_ie; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - u8 *vht_ie_capab, *vht_ie_operation; -#endif - SLSI_UNUSED_PARAMETER(bssid); - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_START.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - mgmt = (struct ieee80211_mgmt *)settings->beacon.head; - beacon_ie_head_len = settings->beacon.head_len - ((u8 *)mgmt->u.beacon.variable - (u8 *)mgmt); - - /* For port enabling, save the privacy bit used in assoc response or beacon */ - ndev_vif->ap.privacy = (mgmt->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY); - ndev_vif->ap.qos_enabled = (mgmt->u.beacon.capab_info & WLAN_CAPABILITY_QOS); - - switch (auth_type) { - case NL80211_AUTHTYPE_OPEN_SYSTEM: - case NL80211_AUTHTYPE_SHARED_KEY: - break; - case NL80211_AUTHTYPE_AUTOMATIC: - auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; - if (settings->privacy && settings->crypto.cipher_group == 0) - auth_type = NL80211_AUTHTYPE_SHARED_KEY; - break; - default: - SLSI_NET_ERR(dev, "Unsupported auth_type: %d\n", auth_type); - return -EOPNOTSUPP; - } - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_start_req(vif:%u, bssid:%pM, ssid:%.*s, hidden:%d)\n", ndev_vif->ifnum, bssid, (int)settings->ssid_len, settings->ssid, settings->hidden_ssid); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if (append_vht_ies) - vht_ies_len = SLSI_VHT_CAPABILITIES_IE_LEN + SLSI_VHT_OPERATION_IE_LEN; - - recv_vht_capab_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, settings->beacon.tail, - settings->beacon.tail_len); - if (recv_vht_capab_ie) - vht_ies_len -= (recv_vht_capab_ie[1] + 2); - - recv_vht_operation_ie = cfg80211_find_ie(WLAN_EID_VHT_OPERATION, settings->beacon.tail, - settings->beacon.tail_len); - if (recv_vht_operation_ie) - vht_ies_len -= (recv_vht_operation_ie[1] + 2); - - if (ndev_vif->chandef->width == NL80211_CHAN_WIDTH_80) { - /* Ext Capab are not advertised by driver and so the IE would not be sent by hostapd. - * Frame the IE in driver and set the required bit(s). - */ - SLSI_NET_DBG1(dev, SLSI_MLME, "VHT - Ext Capab IE to be included\n"); - ext_capab_len = SLSI_AP_EXT_CAPAB_IE_LEN_MAX; - } -#endif - - if (settings->hidden_ssid == 1) - req = fapi_alloc(mlme_start_req, MLME_START_REQ, ndev_vif->ifnum, settings->ssid_len + beacon_ie_head_len + settings->beacon.tail_len + vht_ies_len + ext_capab_len); - else - req = fapi_alloc(mlme_start_req, MLME_START_REQ, ndev_vif->ifnum, beacon_ie_head_len + settings->beacon.tail_len + vht_ies_len + ext_capab_len); - - if (!req) - return -ENOMEM; - fapi_set_memcpy(req, u.mlme_start_req.bssid, dev->dev_addr); - fapi_set_u16(req, u.mlme_start_req.beacon_period, settings->beacon_interval); - fapi_set_u16(req, u.mlme_start_req.dtim_period, settings->dtim_period); - fapi_set_u16(req, u.mlme_start_req.capability_information, le16_to_cpu(mgmt->u.beacon.capab_info)); - fapi_set_u16(req, u.mlme_start_req.authentication_type, auth_type); - fapi_set_u16(req, u.mlme_start_req.hidden_ssid, settings->hidden_ssid < 3 ? settings->hidden_ssid : NL80211_HIDDEN_SSID_ZERO_LEN); - - fw_freq = ndev_vif->chan->center_freq; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - chan_info = slsi_get_chann_info(sdev, ndev_vif->chandef); -#else - chan_info = slsi_get_chann_info(sdev, ndev_vif->channel_type); -#endif - if ((chan_info & 20) != 20) - fw_freq = slsi_get_center_freq1(sdev, chan_info, fw_freq); - - fapi_set_u16(req, u.mlme_start_req.channel_frequency, (2 * fw_freq)); - fapi_set_u16(req, u.mlme_start_req.channel_information, chan_info); - ndev_vif->ap.channel_freq = fw_freq; - - /* Addition of SSID IE in mlme_start_req for hiddenSSID case */ - if (settings->hidden_ssid != 0) { - p = fapi_append_data(req, NULL, 2 + settings->ssid_len); - if (!p) { - slsi_kfree_skb(req); - return -EINVAL; - } - *p++ = WLAN_EID_SSID; - *p++ = settings->ssid_len; - memcpy(p, settings->ssid, settings->ssid_len); - } - - if (beacon_ie_head_len && settings->hidden_ssid == 0) - fapi_append_data(req, mgmt->u.beacon.variable, beacon_ie_head_len); - else if (beacon_ie_head_len && settings->hidden_ssid == 1) - fapi_append_data(req, mgmt->u.beacon.variable + 2, beacon_ie_head_len - 2); - else if (beacon_ie_head_len && settings->hidden_ssid == 2) - fapi_append_data(req, mgmt->u.beacon.variable + 2 + settings->ssid_len, beacon_ie_head_len - (2 + settings->ssid_len)); - - if (settings->beacon.tail_len) - slsi_mlme_start_prepare_ies(req, ndev_vif, settings, wpa_ie_pos, wmm_ie_pos); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - if ((append_vht_ies) && !slsi_prepare_vht_ies(dev, &vht_ie_capab, &vht_ie_operation)) { - fapi_append_data(req, vht_ie_capab, SLSI_VHT_CAPABILITIES_IE_LEN); - fapi_append_data(req, vht_ie_operation, SLSI_VHT_OPERATION_IE_LEN); - kfree(vht_ie_capab); - kfree(vht_ie_operation); - } -#endif - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_START_CFM); - if (!cfm) - return -EIO; - if (fapi_get_u16(cfm, u.mlme_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_start_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_start_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -static const u8 *slsi_mlme_connect_get_sec_ie(struct cfg80211_connect_params *sme, int *sec_ie_len) -{ - u16 version; - const u8 *ptr = NULL; - - if (sme->crypto.wpa_versions == 0) { - /* WAPI */ - ptr = cfg80211_find_ie(SLSI_WLAN_EID_WAPI, sme->ie, sme->ie_len); - if (ptr) { - version = ptr[3] << 8 | ptr[2]; - if (version != 1) { - SLSI_ERR_NODEV("Unexpected version (%d) in WAPI ie\n", version); - return NULL; - } - } - } else if (sme->crypto.wpa_versions == 2) { - /* RSN */ - ptr = cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len); - - if (ptr) { - /* version index is 2 for RSN */ - version = ptr[2 + 1] << 8 | ptr[2]; - if (version != 1) { - SLSI_ERR_NODEV("Unexpected version (%d) in rsn ie\n", version); - return NULL; - } - } - } - *sec_ie_len = ptr ? ptr[1] + 2 : 0; - return ptr; -} - -/* If is_copy is true copy the required IEs from connect_ie to ie_dest. else - * calculate the required ie length - */ -static int slsi_mlme_connect_info_elems_ie_prep(struct slsi_dev *sdev, const u8 *connect_ie, - const size_t connect_ie_len, bool is_copy, u8 *ie_dest, int ie_dest_len) -{ - const u8 *ie_pos = NULL; - int info_elem_length = 0; - u16 curr_ie_len; - int i = 0; - u8 ie_eid[] = {SLSI_WLAN_EID_INTERWORKING, - SLSI_WLAN_EID_EXTENSION, - WLAN_EID_VENDOR_SPECIFIC}; /*Vendor IE has to be the last element */ - - if (is_copy && (!ie_dest || ie_dest_len == 0)) - return -EINVAL; - - for (i = 0; i < sizeof(ie_eid) / sizeof(u8); i++) { - ie_pos = cfg80211_find_ie(ie_eid[i], connect_ie, connect_ie_len); - if (ie_pos) { - if (ie_eid[i] == WLAN_EID_VENDOR_SPECIFIC) /*Vendor IE will be the last element */ - curr_ie_len = connect_ie_len - (ie_pos - connect_ie); - else - curr_ie_len = *(ie_pos + 1) + 2; - SLSI_DBG2(sdev, SLSI_MLME, "IE[%d] is present having length:%d\n", ie_eid[i], curr_ie_len); - if (is_copy) { - if (ie_dest_len >= curr_ie_len) { - memcpy(ie_dest, ie_pos, curr_ie_len); - ie_dest += curr_ie_len; - /* free space avail in ie_dest for next ie*/ - ie_dest_len -= curr_ie_len; - } else { - SLSI_ERR_NODEV("IE[%d] extract error (ie_copy_l:%d, c_ie_l:%d):\n", ie_eid[i], - ie_dest_len, curr_ie_len); - return -EINVAL; - } - } else { - info_elem_length += curr_ie_len; - } - } - } - - if (sdev->device_config.qos_info != -1) { - if (is_copy) { - if (ie_dest_len >= 9) { - int pos = 0; - - ie_dest[pos++] = SLSI_WLAN_EID_VENDOR_SPECIFIC; - ie_dest[pos++] = 0x07; - ie_dest[pos++] = 0x00; - ie_dest[pos++] = 0x50; - ie_dest[pos++] = 0xf2; - ie_dest[pos++] = WLAN_OUI_TYPE_MICROSOFT_WMM; - ie_dest[pos++] = WMM_OUI_SUBTYPE_INFORMATION_ELEMENT; - ie_dest[pos++] = WMM_VERSION; - ie_dest[pos++] = sdev->device_config.qos_info & 0x0F; - ie_dest += pos; - ie_dest_len -= pos; - } else { - SLSI_ERR_NODEV("Required 9bytes but left:%d\n", ie_dest_len); - return -EINVAL; - } - } else { - info_elem_length += 9; - } - } - return info_elem_length; -} - -static int slsi_mlme_connect_info_elements(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int info_elem_length = 0; - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u8 *p; - - info_elem_length = slsi_mlme_connect_info_elems_ie_prep(sdev, sme->ie, sme->ie_len, false, NULL, 0); - - /* NO IE required in MLME-ADD-INFO-ELEMENTS */ - if (info_elem_length <= 0) - return info_elem_length; - - req = fapi_alloc(mlme_add_info_elements_req, MLME_ADD_INFO_ELEMENTS_REQ, - ndev_vif->ifnum, info_elem_length); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_add_info_elements_req.purpose, FAPI_PURPOSE_ASSOCIATION_REQUEST); - - p = fapi_append_data(req, NULL, info_elem_length); - if (!p) { - slsi_kfree_skb(req); - return -EINVAL; - } - - (void)slsi_mlme_connect_info_elems_ie_prep(sdev, sme->ie, sme->ie_len, true, p, info_elem_length); - - /* backup ies */ - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - if (ndev_vif->sta.assoc_req_add_info_elem_len) - kfree(ndev_vif->sta.assoc_req_add_info_elem); - ndev_vif->sta.assoc_req_add_info_elem_len = 0; - - ndev_vif->sta.assoc_req_add_info_elem = kmalloc(info_elem_length, GFP_KERNEL); - if (ndev_vif->sta.assoc_req_add_info_elem) { - memcpy(ndev_vif->sta.assoc_req_add_info_elem, p, info_elem_length); - ndev_vif->sta.assoc_req_add_info_elem_len = info_elem_length; - } else { - SLSI_WARN(sdev, "No mem for ndev_vif->sta.assoc_req_add_info_elem size %d\n", info_elem_length); - } - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_add_info_elements_req(vif:%u)\n", ndev_vif->ifnum); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ADD_INFO_ELEMENTS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_add_info_elements_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_add_info_elements_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_connect_cfm.result_code)); - r = -EINVAL; - } - - if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, sme->ie, sme->ie_len)) - ndev_vif->sta.is_wps = true; - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_connect(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_connect_params *sme, struct ieee80211_channel *channel, const u8 *bssid) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u8 *p; - enum nl80211_auth_type auth_type = sme->auth_type; - u8 mac_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - struct key_params slsi_key; - const u8 *sec_ie = NULL; - int sec_ie_len = 0; - - memset(&slsi_key, 0, sizeof(slsi_key)); - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_CONNECT.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (WARN(!bssid, "BSSID is Null")) - return -EINVAL; - - if (WARN(!sme->ssid_len, "SSID is Null")) - return -EINVAL; - - switch (auth_type) { - case NL80211_AUTHTYPE_OPEN_SYSTEM: - case NL80211_AUTHTYPE_SHARED_KEY: - break; - case NL80211_AUTHTYPE_SAE: - auth_type = NL80211_AUTHTYPE_NETWORK_EAP; - break; - case NL80211_AUTHTYPE_AUTOMATIC: - /* In case of WEP, need to try both open and shared. - * FW does this if auth is shared_key. So set it to shared. - */ - if (sme->privacy && - (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40 || - sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)) - auth_type = NL80211_AUTHTYPE_SHARED_KEY; - else - auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; - break; - default: - SLSI_NET_ERR(dev, "Unsupported auth_type: %d\n", auth_type); - return -EOPNOTSUPP; - } - - /* We save the WEP key for shared authentication. */ - if ((auth_type == NL80211_AUTHTYPE_SHARED_KEY) && - ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || - (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)) && - (ndev_vif->vif_type == FAPI_VIFTYPE_STATION)) { - SLSI_NET_DBG3(dev, SLSI_MLME, "key len (%d)\n", sme->key_len); - slsi_key.key = (u8 *)sme->key; - if (!slsi_key.key) - return -EINVAL; - slsi_key.key_len = sme->key_len; - slsi_key.seq_len = 0; - if (sme->crypto.n_ciphers_pairwise) - slsi_key.cipher = sme->crypto.ciphers_pairwise[0]; - - r = slsi_mlme_set_key(sdev, dev, sme->key_idx, FAPI_KEYTYPE_WEP, mac_addr, &slsi_key); - if (r != 0) { - SLSI_NET_ERR(dev, "Error Setting Shared key (%d)", r); - return r; - } - } - - /*Do not check sme->ie as wpa_supplicant sends some invalid value in it even if ie_len is zero .*/ - if (sme->ie_len) { - r = slsi_mlme_connect_info_elements(sdev, dev, sme); - if (r) - return r; - - sec_ie = slsi_mlme_connect_get_sec_ie(sme, &sec_ie_len); - if (sec_ie_len < 0) { - SLSI_NET_ERR(dev, "ERROR preparing Security IEs\n"); - return sec_ie_len; - } - } - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connect_req(vif:%u, bssid:%pM, ssid:%.*s)\n", ndev_vif->ifnum, bssid, (int)sme->ssid_len, sme->ssid); - req = fapi_alloc(mlme_connect_req, MLME_CONNECT_REQ, ndev_vif->ifnum, - 2 + sme->ssid_len + /*SSID IE*/ - sec_ie_len); /*WPA/WPA2/WAPI/OSEN*/ - if (!req) - return -ENOMEM; - - fapi_set_memcpy(req, u.mlme_connect_req.bssid, bssid); - fapi_set_u16(req, u.mlme_connect_req.authentication_type, auth_type); - /* Need to double the freq for the firmware */ - fapi_set_u16(req, u.mlme_connect_req.channel_frequency, (2 * channel->center_freq)); - - p = fapi_append_data(req, NULL, 2 + sme->ssid_len + sec_ie_len); - if (!p) { - slsi_kfree_skb(req); - return -EINVAL; - } - *p++ = WLAN_EID_SSID; - *p++ = sme->ssid_len; - memcpy(p, sme->ssid, sme->ssid_len); - p += sme->ssid_len; - - if (sec_ie_len) - memcpy(p, sec_ie, sec_ie_len); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_CONNECT_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_connect_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_connect_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_connect_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -void slsi_mlme_connect_resp(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_CONNECT_RESP\n"); - return; - } - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connect_resp(vif:%u)\n", ndev_vif->ifnum); - req = fapi_alloc(mlme_connect_res, MLME_CONNECT_RES, ndev_vif->ifnum, 0); - if (!req) - return; - - cfm = slsi_mlme_req_no_cfm(sdev, dev, req); - WARN_ON(cfm); -} - -void slsi_mlme_connected_resp(struct slsi_dev *sdev, struct net_device *dev, u16 peer_index) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_CONNECT_RESP\n"); - return; - } - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connected_resp(vif:%u, peer_index:%d)\n", ndev_vif->ifnum, peer_index); - req = fapi_alloc(mlme_connected_res, MLME_CONNECTED_RES, ndev_vif->ifnum, 0); - if (!req) { - SLSI_NET_ERR(dev, "mlme-connected-response :: memory allocation failed\n"); - return; - } - - fapi_set_u16(req, u.mlme_connected_res.association_identifier, peer_index); - slsi_mlme_req_no_cfm(sdev, dev, req); -} - -void slsi_mlme_roamed_resp(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_ROAMED_RESP\n"); - return; - } - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_roamed_resp\n"); - req = fapi_alloc(mlme_roamed_res, MLME_ROAMED_RES, ndev_vif->ifnum, 0); - if (!req) - return; - - cfm = slsi_mlme_req_no_cfm(sdev, dev, req); - WARN_ON(cfm); -} - -/* Null check for cfm done in caller function */ -bool slsi_disconnect_cfm_validate(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm) -{ - int result = fapi_get_u16(cfm, u.mlme_disconnect_cfm.result_code); - bool r = false; - - SLSI_UNUSED_PARAMETER(sdev); - - if (WARN_ON(!dev)) - goto exit; - - if (result == FAPI_RESULTCODE_SUCCESS) - r = true; - /* Not present code would mean peer is already disconnected and hence no ind (could be race scenario), don't log as error */ - else if (result != FAPI_RESULTCODE_NOT_PRESENT) - SLSI_NET_ERR(dev, "mlme_disconnect_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_disconnect_cfm.result_code)); - -exit: - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *mac, u16 reason_code, bool wait_ind) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_DISCONNECT.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_disconnect_req(vif:%u, bssid:%pM, reason:%d)\n", ndev_vif->ifnum, mac, reason_code); - - req = fapi_alloc(mlme_disconnect_req, MLME_DISCONNECT_REQ, ndev_vif->ifnum, - ndev_vif->sta.vendor_disconnect_ies_len); - - if (!req) - return -ENOMEM; - SLSI_INFO(sdev, "Send DEAUTH, reason = %d\n", reason_code); - fapi_set_u16(req, u.mlme_disconnect_req.reason_code, reason_code); - if (ndev_vif->sta.vendor_disconnect_ies_len > 0) - fapi_append_data(req, ndev_vif->sta.vendor_disconnect_ies, ndev_vif->sta.vendor_disconnect_ies_len); - kfree(ndev_vif->sta.vendor_disconnect_ies); - ndev_vif->sta.vendor_disconnect_ies = NULL; - ndev_vif->sta.vendor_disconnect_ies_len = 0; - - if (mac) - fapi_set_memcpy(req, u.mlme_disconnect_req.peer_sta_address, mac); - else - fapi_set_memset(req, u.mlme_disconnect_req.peer_sta_address, 0); - if (wait_ind) { - rx = slsi_mlme_req_cfm_ind(sdev, dev, req, MLME_DISCONNECT_CFM, MLME_DISCONNECT_IND, slsi_disconnect_cfm_validate); - if (!rx) { - SLSI_NET_ERR(dev, "mlme_disconnect_cfm() ERROR\n"); - r = -EINVAL; - } - } else { - rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_DISCONNECT_CFM); - if (rx) { - if (fapi_get_u16(rx, u.mlme_disconnect_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_disconnect_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_disconnect_cfm.result_code)); - r = -EINVAL; - } - } else { - r = -EIO; - } - } - - slsi_kfree_skb(rx); - return r; -} - -int slsi_mlme_set_key(struct slsi_dev *sdev, struct net_device *dev, u16 key_id, u16 key_type, const u8 *address, struct key_params *key) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_SETKEYS.request\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_setkeys_req(key_id:%d, key_type:%d, address:%pM, length:%d, cipher:0x%.8X)\n", key_id, key_type, address, key->key_len, key->cipher); - req = fapi_alloc(mlme_setkeys_req, MLME_SETKEYS_REQ, ndev_vif->ifnum, key->key_len + 1); /* + 1 for the wep key index */ - if (!req) - return -ENOMEM; - fapi_set_u16(req, u.mlme_setkeys_req.length, key->key_len * 8); - fapi_set_u16(req, u.mlme_setkeys_req.key_id, key_id); - fapi_set_u16(req, u.mlme_setkeys_req.key_type, key_type); - fapi_set_memcpy(req, u.mlme_setkeys_req.address, address); - fapi_set_memset(req, u.mlme_setkeys_req.sequence_number, 0x00); - - if (key->seq_len && key->seq) { - int i; - u16 temp_seq; - - SLSI_NET_DBG3(dev, SLSI_MLME, "mlme_setkeys_req(key->seq_len:%d)\n", key->seq_len); - - /* Sequence would be in little endian format - * If sequence is say key->seq is - * 04 03 02 01 00 00 00 00, it would be encoded as : - * 0x0304 0x0102 0x0000 0x0000 for firmware - */ - for (i = 0; i < key->seq_len; i += 2) { - temp_seq = (u16)(key->seq[i + 1] << 8) | (u16)(key->seq[i]); - fapi_set_u16(req, u.mlme_setkeys_req.sequence_number[i / 2], temp_seq); - } - } - - fapi_set_u32(req, u.mlme_setkeys_req.cipher_suite_selector, key->cipher); - - if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) { - u8 wep_key_id = (u8)key_id; - - if (key_id > 3) - SLSI_NET_WARN(dev, "Key ID is greater than 3"); - /* Incase of WEP key index is appended before key. - * So increment length by one - */ - fapi_set_u16(req, u.mlme_setkeys_req.length, (key->key_len + 1) * 8); - fapi_append_data(req, &wep_key_id, 1); - } - fapi_append_data(req, key->key, key->key_len); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SETKEYS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_setkeys_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_setkeys_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_setkeys_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_get_key(struct slsi_dev *sdev, struct net_device *dev, u16 key_id, u16 key_type, u8 *seq, int *seq_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_get_key_sequence_req(key_id:%d, key_type:%d)\n", key_id, key_type); - req = fapi_alloc(mlme_get_key_sequence_req, MLME_GET_KEY_SEQUENCE_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - fapi_set_u16(req, u.mlme_get_key_sequence_req.key_id, key_id); - fapi_set_u16(req, u.mlme_get_key_sequence_req.key_type, key_type); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_GET_KEY_SEQUENCE_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_get_key_sequence_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_get_key_sequence_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_get_key_sequence_cfm.result_code)); - r = -ENOENT; - } else { - int i; - u16 temp_seq; - - /* For WPA2 Key RSC - 8 octets. For WPAI, it would be 16 octets (code would need to be updated) - * Length is not available in cfm but even if max length 8 is assigned, it should be ok as other octets - * would be padded with 0s - */ - *seq_len = 8; - - /* Sequence from firmware is of a[8] type u16 (16 octets) and only 8 octets are required for WPA/WPA2. - * If sequence is say 0x01 0x02 0x03 0x04 with 0x01 as MSB and 0x04 as LSB then - * it would be encoded as: 0x0304 0x0102 by firmware. - * Sequence is expected to be returned in little endian - */ - - for (i = 0; i < *seq_len / 2; i++) { - temp_seq = fapi_get_u16(cfm, u.mlme_get_key_sequence_cfm.sequence_number[i]); - *seq = (u8)(temp_seq & 0xFF); - *(seq + 1) = (u8)((temp_seq >> 8) & 0xFF); - - seq += 2; - } - } - - slsi_kfree_skb(cfm); - return r; -} - -void slsi_calc_max_data_rate(struct net_device *dev, u8 bandwidth, u8 antenna_mode) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u8 bandwidth_index, sta_mode, mcs_index; - - if (bandwidth == 0 || antenna_mode > 3) { - SLSI_NET_ERR(dev, "MIB value is wrong."); - return; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - /* Bandwidth (BW): 0x0= 20 MHz, 0x1= 40 MHz, 0x2= 80 MHz, 0x3= 160/ 80+80 MHz. 0x3 is not supported */ - bandwidth_index = bandwidth / 40; - sta_mode = slsi_sta_ieee80211_mode(dev, ndev_vif->sta.sta_bss->channel->center_freq); - - if (sta_mode == SLSI_80211_MODE_11B) { - ndev_vif->sta.max_rate_mbps = 11; - } else if (sta_mode == SLSI_80211_MODE_11G || sta_mode == SLSI_80211_MODE_11A) { - ndev_vif->sta.max_rate_mbps = 54; - } else if (sta_mode == SLSI_80211_MODE_11N) { /* max mcs index = 7 */ - ndev_vif->sta.max_rate_mbps = (unsigned long)(slsi_rates_table[bandwidth_index][1][7] * (antenna_mode + 1)) / 10; - } else if (sta_mode == SLSI_80211_MODE_11AC) { - if (bandwidth_index == 0) - mcs_index = 8; - else - mcs_index = 9; - ndev_vif->sta.max_rate_mbps = (unsigned long)(slsi_rates_table[bandwidth_index][1][mcs_index] * (antenna_mode + 1)) / 10; - } - SLSI_NET_INFO(dev, "sta_mode : %u, freq : %u, bandwidth : %u, antenna_mode : %u, max_rate_mbps : %u\n", - sta_mode, ndev_vif->sta.sta_bss->channel->center_freq, bandwidth, antenna_mode, ndev_vif->sta.max_rate_mbps); -} - -void slsi_decode_fw_rate(u16 fw_rate, struct rate_info *rate, unsigned long *data_rate_mbps) -{ - const int fw_rate_idx_to_80211_rate[] = { 0, 10, 20, 55, 60, 90, 110, 120, 180, 240, 360, 480, 540 }; - - if (rate) { - rate->flags = 0; - rate->legacy = 0; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) - rate->bw = 0; -#endif - } - - if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_NON_HT_SELECTED) { - u16 fw_rate_idx = fw_rate & SLSI_FW_API_RATE_INDEX_FIELD; - - if (fw_rate > 0 && fw_rate_idx < ARRAY_SIZE(fw_rate_idx_to_80211_rate)) { - if (rate) - rate->legacy = fw_rate_idx_to_80211_rate[fw_rate_idx]; - if (data_rate_mbps) - *data_rate_mbps = fw_rate_idx_to_80211_rate[fw_rate_idx] / 10; - } - } else if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_HT_SELECTED) { - u8 mcs_idx = SLSI_FW_API_RATE_HT_MCS_FIELD & fw_rate; - u8 nss = ((SLSI_FW_API_RATE_HT_NSS_FIELD & fw_rate) >> 6) + 1; - - if (rate) { - rate->flags |= RATE_INFO_FLAGS_MCS; - rate->mcs = mcs_idx; - - if ((fw_rate & SLSI_FW_API_RATE_BW_FIELD) == SLSI_FW_API_RATE_BW_40MHZ) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) - rate->bw |= RATE_INFO_BW_40; -#else - rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; -#endif - if (fw_rate & SLSI_FW_API_RATE_SGI) - rate->flags |= RATE_INFO_FLAGS_SHORT_GI; - } - - if (data_rate_mbps) { - int chan_bw_idx; - int gi_idx; - - chan_bw_idx = (fw_rate & SLSI_FW_API_RATE_BW_FIELD) >> 9; - gi_idx = ((fw_rate & SLSI_FW_API_RATE_SGI) == SLSI_FW_API_RATE_SGI) ? 1 : 0; - - /* nss will be 1 when mcs_idx <= 7 or mcs == 32 */ - if (chan_bw_idx < 2) { - if (mcs_idx <= 7) { - *data_rate_mbps = slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx] / 10; - } else if (mcs_idx <= 15) { - *data_rate_mbps = (unsigned long)(nss * slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx - 8]) / 10; - } else if (mcs_idx == 32 && chan_bw_idx == 1) { - /* TODO: Fix this : unsigned long will not hold decimal values */ - if (gi_idx == 1) - *data_rate_mbps = (unsigned long) 6.7; - else - *data_rate_mbps = 6; - } - } else { - SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x, nss : %d\n", - fw_rate, chan_bw_idx, mcs_idx, nss); - } - } - } else if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_VHT_SELECTED) { - int chan_bw_idx; - int gi_idx; - int mcs_idx; - u8 nss; - - /* report vht rate in legacy units and not as mcs index. reason: upper layers may still be not - * updated with vht msc table. - */ - chan_bw_idx = (fw_rate & SLSI_FW_API_RATE_BW_FIELD) >> 9; - gi_idx = ((fw_rate & SLSI_FW_API_RATE_SGI) == SLSI_FW_API_RATE_SGI) ? 1 : 0; - /* Calculate NSS --> bits 6 to 4*/ - nss = ((SLSI_FW_API_RATE_VHT_NSS_FIELD & fw_rate) >> 4) + 1; - mcs_idx = SLSI_FW_API_RATE_VHT_MCS_FIELD & fw_rate; - /* Bandwidth (BW): 0x0= 20 MHz, 0x1= 40 MHz, 0x2= 80 MHz, 0x3= 160/ 80+80 MHz. 0x3 is not supported */ - if ((chan_bw_idx <= 2) && (mcs_idx <= 9)) { - if (rate) - rate->legacy = nss * slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx]; - if (data_rate_mbps) - *data_rate_mbps = (unsigned long)(nss * slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx]) / 10; - } else { - SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x,nss : %d\n", fw_rate, chan_bw_idx, mcs_idx, nss); - } - } -} - -int slsi_mlme_get_sinfo_mib(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_peer *peer) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - u8 bandwidth = 0, antenna_mode = 4; - int data_length = 0; - int r = 0; - int mib_index = 0; - static const struct slsi_mib_get_entry get_values[] = { - { SLSI_PSID_UNIFI_TX_DATA_RATE, { 0, 0 } }, /* to get STATION_INFO_TX_BITRATE*/ - { SLSI_PSID_UNIFI_RX_DATA_RATE, { 0, 0 } }, /* to get STATION_INFO_RX_BITRATE*/ - { SLSI_PSID_UNIFI_RSSI, { 0, 0 } }, /* to get STATION_INFO_SIGNAL_AVG*/ - { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 3, 0 } }, /* bad_fcs_count*/ - { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 25, 0 } }, /* mac_bad_sig_count*/ - { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 30, 0 } }, /* rx_error_count*/ - { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS, { 1, 0 } }, /*tx good count*/ - { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS, { 2, 0 } }, /*tx bad count*/ - { SLSI_PSID_UNIFI_FRAME_RX_COUNTERS, { 1, 0 } }, /*rx good count*/ - { SLSI_PSID_UNIFI_CURRENT_BSS_BANDWIDTH, { 0, 0 } }, /* bss bandwidth */ -#ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS - { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS, { 3, 0 } }, /*tx retry count*/ -#endif - { SLSI_PSID_UNIFI_STA_VIF_LINK_NSS, { 0, 0 } } /* current nss */ - }; - int rx_counter = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (!peer) { - SLSI_WARN(sdev, "Peer Not available\n"); - return -EINVAL; - } - - /*check if function is called within given period*/ - if (__ratelimit(&peer->sinfo_mib_get_rs)) - return 0; - - r = slsi_mib_encode_get_list(&mibreq, (sizeof(get_values) / sizeof(struct slsi_mib_get_entry)), - get_values); - if (r != SLSI_MIB_STATUS_SUCCESS) - return -ENOMEM; - - /* Fixed fields len (5) : 2 bytes(PSID) + 2 bytes (Len) + 1 byte (VLDATA header ) [10 for 2 PSIDs] - * Data : 3*2 bytes for SLSI_PSID_UNIFI_TX_DATA_RATE & SLSI_PSID_UNIFI_RX_DATA_RATE, 1 byte for SLSI_PSID_UNIFI_RSSI - * 10*7 bytes for 3 Throughput Mib's and 4 counter Mib's - */ - mibrsp.dataLength = 114; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_NET_DBG1(dev, SLSI_MLME, "failed to allocate memory\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, dev, mibreq.data, mibreq.dataLength, mibrsp.data, - mibrsp.dataLength, &data_length); - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = (u32)data_length; - values = slsi_mib_decode_get_list(&mibrsp, - (sizeof(get_values) / sizeof(struct slsi_mib_get_entry)), get_values); - if (!values) { - SLSI_NET_DBG1(dev, SLSI_MLME, "mib decode list failed\n"); - kfree(mibrsp.data); - return -ENOMEM; - } - - if (values[mib_index].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT); - slsi_decode_fw_rate((u16)values[mib_index].u.uintValue, &peer->sinfo.txrate, &ndev_vif->sta.data_rate_mbps); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) - peer->sinfo.filled |= BIT(NL80211_STA_INFO_TX_BITRATE); -#else - peer->sinfo.filled |= STATION_INFO_TX_BITRATE; -#endif - SLSI_DBG3(sdev, SLSI_MLME, "SLSI_PSID_UNIFI_TX_DATA_RATE = 0x%x\n", - values[mib_index].u.uintValue); - } - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT); - slsi_decode_fw_rate((u16)values[mib_index].u.uintValue, &peer->sinfo.rxrate, NULL); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) - peer->sinfo.filled |= BIT(NL80211_STA_INFO_RX_BITRATE); -#else - peer->sinfo.filled |= STATION_INFO_RX_BITRATE; -#endif - SLSI_DBG3(sdev, SLSI_MLME, "SLSI_PSID_UNIFI_RX_DATA_RATE = 0x%x\n", - values[mib_index].u.uintValue); - } - else - SLSI_DBG3(sdev, SLSI_MLME, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - - if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { - SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_INT); - if (values[mib_index].u.intValue >= 0) - peer->sinfo.signal = -1; - else - peer->sinfo.signal = (s8)values[mib_index].u.intValue; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) - peer->sinfo.filled |= BIT(NL80211_STA_INFO_SIGNAL); -#else - peer->sinfo.filled |= STATION_INFO_SIGNAL; -#endif - SLSI_DBG3(sdev, SLSI_MLME, "SLSI_PSID_UNIFI_RSSI = %d\n", - values[mib_index].u.intValue); - } - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - rx_counter += values[mib_index].u.uintValue; /*bad_fcs_count*/ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - rx_counter += values[mib_index].u.uintValue; /*mac_bad_sig_count*/ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - rx_counter += values[mib_index].u.uintValue; /*rx_error_count*/ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - peer->sinfo.tx_packets = values[mib_index].u.uintValue; /*tx good count*/ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - peer->sinfo.tx_failed = values[mib_index].u.uintValue; /*tx bad count*/ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - peer->sinfo.rx_packets = values[mib_index].u.uintValue; /*rx good count*/ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - bandwidth = values[mib_index].u.uintValue; /* bss bandwidth */ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); -#ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) - peer->sinfo.tx_retries = values[mib_index].u.uintValue; /*tx retry count*/ - else - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); -#endif - if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) { - antenna_mode = values[mib_index].u.uintValue; /* current nss */ - slsi_calc_max_data_rate(dev, bandwidth, antenna_mode); - } else { - SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid); - } - - peer->sinfo.rx_dropped_misc = rx_counter; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) - peer->sinfo.filled |= BIT(NL80211_STA_INFO_TX_FAILED) | BIT(NL80211_STA_INFO_RX_DROP_MISC) | - BIT(NL80211_STA_INFO_TX_PACKETS) | BIT(NL80211_STA_INFO_RX_PACKETS); -#ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS - peer->sinfo.filled |= BIT(NL80211_STA_INFO_TX_RETRIES); -#endif -#endif - } else { - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_get_req failed(result:0x%4x)\n", r); - } - - kfree(mibrsp.data); - kfree(values); - return r; -} - -int slsi_mlme_connect_scan(struct slsi_dev *sdev, struct net_device *dev, - u32 n_ssids, struct cfg80211_ssid *ssids, struct ieee80211_channel *channel) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int r = 0; - struct ieee80211_channel **scan_channels = NULL; - struct ieee80211_channel **add_scan_channels; - int n_channels = 0; - struct sk_buff *scan; - struct cfg80211_scan_info info = {.aborted = true}; - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) { - SLSI_NET_DBG3(dev, SLSI_MLME, "stop on-going Scan\n"); - (void)slsi_mlme_del_scan(sdev, dev, ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID, false); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, &info); -#else - cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, true); -#endif - - ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req = NULL; - } - - if (!channel) { - enum nl80211_band band; - struct wiphy *wiphy = sdev->wiphy; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - for (band = 0; band < NUM_NL80211_BANDS; band++) { -#else - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { -#endif - if (!wiphy->bands[band]) - continue; - n_channels += wiphy->bands[band]->n_channels; - } - - WARN_ON(n_channels == 0); - scan_channels = kmalloc_array((size_t)n_channels, sizeof(*scan_channels), GFP_KERNEL); - if (!scan_channels) { - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return -ENOMEM; - } - n_channels = 0; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - for (band = 0; band < NUM_NL80211_BANDS; band++) { -#else - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { -#endif - int j; - - if (!wiphy->bands[band]) - continue; - for (j = 0; j < wiphy->bands[band]->n_channels; j++) - if (!(wiphy->bands[band]->channels[j].flags & IEEE80211_CHAN_DISABLED)) { - scan_channels[n_channels] = &wiphy->bands[band]->channels[j]; - n_channels++; - } - } - add_scan_channels = scan_channels; - } else { - n_channels = 1; - add_scan_channels = &channel; - } - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = true; - r = slsi_mlme_add_scan(sdev, - dev, - FAPI_SCANTYPE_FULL_SCAN, - FAPI_REPORTMODE_REAL_TIME, - n_ssids, - ssids, - n_channels, - add_scan_channels, - NULL, - ndev_vif->probe_req_ies, - ndev_vif->probe_req_ie_len, - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan); - - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - while (scan) { - slsi_rx_scan_pass_to_cfg80211(sdev, dev, scan); - scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - - kfree(scan_channels); - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = false; - - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return r; -} - -/** - * The powermgt_lock mutex is to ensure atomic update of the power management state. - */ -DEFINE_MUTEX(powermgt_lock); -/** - * The slsi_mlme_powermgt_unlocked() must be called from a context that is synchronised - * with ndev_vif. if called without the ndev_vif mutex already taken, other mechanisms - * must ensure that ndev_vif will exist for the duration of the function. - */ -int slsi_mlme_powermgt_unlocked(struct slsi_dev *sdev, struct net_device *dev, u16 power_mode) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - - mutex_lock(&powermgt_lock); - - if (WARN_ON(!ndev_vif->activated)) { - mutex_unlock(&powermgt_lock); - return -EINVAL; - } - - if (ndev_vif->power_mode == power_mode) { - mutex_unlock(&powermgt_lock); - SLSI_NET_DBG3(dev, SLSI_MLME, "power management mode is same as requested. No changes done\n"); - return 0; - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_powermgt_req(vif:%d, power_management_mode:%d)\n", ndev_vif->ifnum, power_mode); - req = fapi_alloc(mlme_powermgt_req, MLME_POWERMGT_REQ, ndev_vif->ifnum, 0); - if (!req) { - mutex_unlock(&powermgt_lock); - return -ENOMEM; - } - fapi_set_u16(req, u.mlme_powermgt_req.power_management_mode, power_mode); - - rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_POWERMGT_CFM); - if (!rx) { - mutex_unlock(&powermgt_lock); - return -EIO; - } - - if (fapi_get_u16(rx, u.mlme_powermgt_cfm.result_code) == FAPI_RESULTCODE_SUCCESS) { - ndev_vif->power_mode = power_mode; - } else { - SLSI_NET_ERR(dev, "mlme_powermgt_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_powermgt_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(rx); - mutex_unlock(&powermgt_lock); - return r; -} - -int slsi_mlme_powermgt(struct slsi_dev *sdev, struct net_device *dev, u16 power_mode) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - return slsi_mlme_powermgt_unlocked(sdev, dev, power_mode); -} - -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG -int slsi_mlme_synchronised_response(struct slsi_dev *sdev, struct net_device *dev, - struct cfg80211_external_auth_params *params) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - if (ndev_vif->activated) { - SLSI_NET_DBG3(dev, SLSI_MLME, "MLME_SYNCHRONISED_RES\n"); - - req = fapi_alloc(mlme_synchronised_res, MLME_SYNCHRONISED_RES, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_synchronised_res.result_code, params->status); - fapi_set_memcpy(req, u.mlme_synchronised_res.bssid, params->bssid); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_synchronised_response(vif:%d) status:%d\n", - ndev_vif->ifnum, params->status); - cfm = slsi_mlme_req_no_cfm(sdev, dev, req); - if (cfm) - SLSI_NET_ERR(dev, "Received cfm for MLME_SYNCHRONISED_RES\n"); - } else - SLSI_NET_DBG1(dev, SLSI_MLME, "vif is not active"); - - return 0; -} -#endif - -int slsi_mlme_register_action_frame(struct slsi_dev *sdev, struct net_device *dev, u32 af_bitmap_active, u32 af_bitmap_suspended) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - req = fapi_alloc(mlme_register_action_frame_req, MLME_REGISTER_ACTION_FRAME_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u32(req, u.mlme_register_action_frame_req.action_frame_category_bitmap_active, af_bitmap_active); - fapi_set_u32(req, u.mlme_register_action_frame_req.action_frame_category_bitmap_suspended, af_bitmap_suspended); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_register_action_frame(vif:%d, active:%d, suspended:%d)\n", ndev_vif->ifnum, af_bitmap_active, af_bitmap_suspended); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_REGISTER_ACTION_FRAME_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_register_action_frame_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_register_action_frame_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_register_action_frame_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_channel_switch(struct slsi_dev *sdev, struct net_device *dev, u16 center_freq, u16 chan_info) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_channel_switch_req(vif:%d, freq: %d, channel info: 0x%x)\n", ndev_vif->ifnum, center_freq, chan_info); - req = fapi_alloc(mlme_channel_switch_req, MLME_CHANNEL_SWITCH_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_channel_switch_req.channel_frequency, SLSI_FREQ_HOST_TO_FW(center_freq)); - fapi_set_u16(req, u.mlme_channel_switch_req.channel_information, chan_info); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_CHANNEL_SWITCH_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_channel_switch_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_channel_switch_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_channel_switch_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_add_info_elements(struct slsi_dev *sdev, struct net_device *dev, u16 purpose, const u8 *ies, const u16 ies_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u8 *p; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - req = fapi_alloc(mlme_add_info_elements_req, MLME_ADD_INFO_ELEMENTS_REQ, ndev_vif->ifnum, ies_len); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_add_info_elements_req.purpose, purpose); - - if (ies_len != 0) { - p = fapi_append_data(req, ies, ies_len); - if (!p) { - slsi_kfree_skb(req); - return -EINVAL; - } - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_add_info_elements_req(vif:%d, ies_len:%d)\n", ndev_vif->ifnum, ies_len); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ADD_INFO_ELEMENTS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_add_info_elements_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_add_info_elements_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_add_info_elements_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_send_frame_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 msg_type, - u16 host_tag, u32 dwell_time, u32 period) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 len = skb->len; - struct sk_buff *original_skb = 0; - int ret; -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - int is_enhanced_arp_request_frame = 0; -#endif - - /* don't let ARP frames exhaust all the control slots */ - if (msg_type == FAPI_MESSAGETYPE_ARP) { - int free_slots = 0; - - free_slots = hip4_free_ctrl_slots_count(&sdev->hip4_inst); - - if (free_slots < 0) { - SLSI_DBG1(sdev, SLSI_MLME, "drop ARP (error in getting free slot count)\n"); - return free_slots; - } - - if (free_slots < SLSI_MLME_ARP_DROP_FREE_SLOTS_COUNT) { - SLSI_DBG1(sdev, SLSI_MLME, "drop ARP (running out of Control slots:%d)\n", free_slots); - slsi_kfree_skb(skb); - return NETDEV_TX_OK; - } - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - if (ndev_vif->enhanced_arp_detect_enabled && (msg_type == FAPI_MESSAGETYPE_ARP)) { - u8 *frame = skb->data + sizeof(struct ethhdr); - u16 arp_opcode = frame[SLSI_ARP_OPCODE_OFFSET] << 8 | frame[SLSI_ARP_OPCODE_OFFSET + 1]; - - if ((arp_opcode == SLSI_ARP_REQUEST_OPCODE) && - !SLSI_IS_GRATUITOUS_ARP(frame) && - !memcmp(&frame[SLSI_ARP_DEST_IP_ADDR_OFFSET], &ndev_vif->target_ip_addr, 4)) - is_enhanced_arp_request_frame = 1; - } -#endif - } - - /* check for headroom to push signal header; if not available, re-alloc headroom */ - if (skb_headroom(skb) < (fapi_sig_size(mlme_send_frame_req))) { - struct sk_buff *skb2 = NULL; - - skb2 = slsi_skb_realloc_headroom(skb, fapi_sig_size(mlme_send_frame_req)); - if (!skb2) - return -EINVAL; - original_skb = skb; - skb = skb2; - } - len = skb->len; - (void)skb_push(skb, (fapi_sig_size(mlme_send_frame_req))); - - /* fill the signal header */ - fapi_set_u16(skb, id, MLME_SEND_FRAME_REQ); - fapi_set_u16(skb, receiver_pid, 0); - fapi_set_u16(skb, sender_pid, SLSI_TX_PROCESS_ID_MIN); - fapi_set_u16(skb, fw_reference, 0); - - /* fill in signal parameters */ - fapi_set_u16(skb, u.mlme_send_frame_req.vif, ndev_vif->ifnum); - - if (host_tag == 0) - host_tag = slsi_tx_mgmt_host_tag(sdev); - - fapi_set_u16(skb, u.mlme_send_frame_req.host_tag, host_tag); - fapi_set_u16(skb, u.mlme_send_frame_req.data_unit_descriptor, FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME); - fapi_set_u16(skb, u.mlme_send_frame_req.message_type, msg_type); - fapi_set_u16(skb, u.mlme_send_frame_req.channel_frequency, 0); - fapi_set_u32(skb, u.mlme_send_frame_req.dwell_time, dwell_time); - fapi_set_u32(skb, u.mlme_send_frame_req.period, period); - - SLSI_DBG2(sdev, SLSI_MLME, "mlme_send_frame_req(vif:%d, message_type:%d, host_tag:%d)\n", ndev_vif->ifnum, msg_type, host_tag); - /* slsi_tx_control frees the skb. Do not use it after this call. */ - ret = slsi_tx_control(sdev, dev, skb); - if (ret != 0) { - SLSI_WARN(sdev, "failed to send MLME signal(err=%d)\n", ret); - return ret; - } - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - if (is_enhanced_arp_request_frame) { - int i; - - ndev_vif->enhanced_arp_stats.arp_req_count_to_lower_mac++; - for (i = 0; i < SLSI_MAX_ARP_SEND_FRAME; i++) { - if (!ndev_vif->enhanced_arp_host_tag[i]) { - ndev_vif->enhanced_arp_host_tag[i] = host_tag; - break; - } - } - } -#endif - - if (original_skb) - slsi_kfree_skb(original_skb); - - /* as the frame is queued to HIP for transmission, store the host tag of the frames - * to validate the transmission status in MLME-Frame-Transmission.indication. - * Take necessary action based on the type of frame and status of it's transmission - */ - if (msg_type == FAPI_MESSAGETYPE_EAPOL_KEY_M4) { - ndev_vif->sta.m4_host_tag = host_tag; - SLSI_NET_DBG1(dev, SLSI_MLME, "EAPOL-Key M4 frame (host_tag:%d)\n", ndev_vif->sta.m4_host_tag); - } else if (msg_type == FAPI_MESSAGETYPE_EAP_MESSAGE) { - if (!ndev_vif->sta.is_wps && (ndev_vif->iftype == NL80211_IFTYPE_STATION)) { - /* In case of non-P2P station and Enterprise security store the host_tag. - * If transmission of such frame fails, inform supplicant to disconnect. - */ - ndev_vif->sta.eap_hosttag = host_tag; - SLSI_NET_DBG1(dev, SLSI_MLME, "EAP frame (host_tag:%d)\n", ndev_vif->sta.eap_hosttag); - } - } - return ret; -} - -int slsi_mlme_send_frame_mgmt(struct slsi_dev *sdev, struct net_device *dev, const u8 *frame, int frame_len, - u16 data_desc, u16 msg_type, u16 host_tag, u16 freq, u32 dwell_time, u32 period) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u8 *p; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - req = fapi_alloc(mlme_send_frame_req, MLME_SEND_FRAME_REQ, ndev_vif->ifnum, frame_len); - if (!req) { - SLSI_WARN(sdev, "failed to alloc memory\n"); - return -ENOMEM; - } - - fapi_set_u16(req, u.mlme_send_frame_req.host_tag, host_tag); - fapi_set_u16(req, u.mlme_send_frame_req.data_unit_descriptor, data_desc); - fapi_set_u16(req, u.mlme_send_frame_req.message_type, msg_type); - fapi_set_u16(req, u.mlme_send_frame_req.channel_frequency, freq); - fapi_set_u32(req, u.mlme_send_frame_req.dwell_time, dwell_time); - fapi_set_u32(req, u.mlme_send_frame_req.period, period); - - p = fapi_append_data(req, frame, frame_len); - if (!p) { - slsi_kfree_skb(req); - SLSI_WARN(sdev, "failed to append data\n"); - return -EINVAL; - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_send_frame_req(vif:%d, message_type:%d,host_tag:%d)\n", ndev_vif->ifnum, msg_type, host_tag); - slsi_debug_frame(sdev, dev, req, "TX"); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SEND_FRAME_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_send_frame_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_send_frame_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_send_frame_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_reset_dwell_time(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_reset_dwell_time_req (vif:%d)\n", ndev_vif->ifnum); - - req = fapi_alloc(mlme_reset_dwell_time_req, MLME_RESET_DWELL_TIME_REQ, ndev_vif->ifnum, 0); - - if (!req) - return -ENOMEM; - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_RESET_DWELL_TIME_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_reset_dwell_time_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_reset_dwell_time_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_reset_dwell_time_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_set_packet_filter(struct slsi_dev *sdev, struct net_device *dev, - int pkt_filter_len, - u8 num_filters, - struct slsi_mlme_pkt_filter_elem *pkt_filter_elems) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0, i = 0, j = 0; - u8 *p; - u8 index = 0; - - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - - if (WARN_ON(!num_filters)) - return -EINVAL; - - req = fapi_alloc(mlme_set_packet_filter_req, MLME_SET_PACKET_FILTER_REQ, ndev_vif->ifnum, pkt_filter_len); - if (!req) - return -ENOMEM; - - p = fapi_append_data(req, NULL, pkt_filter_len); - if (!p) { - slsi_kfree_skb(req); - return -EINVAL; - } - - for (i = 0; i < num_filters; i++) { - struct slsi_mlme_pkt_filter_elem pkt_filter_elem = pkt_filter_elems[i]; - - memcpy(&p[index], pkt_filter_elem.header, SLSI_PKT_FILTER_ELEM_HDR_LEN); - index += SLSI_PKT_FILTER_ELEM_HDR_LEN; - - for (j = 0; j < pkt_filter_elem.num_pattern_desc; j++) { - p[index++] = pkt_filter_elem.pattern_desc[j].offset; - p[index++] = pkt_filter_elem.pattern_desc[j].mask_length; - memcpy(&p[index], pkt_filter_elem.pattern_desc[j].mask, pkt_filter_elem.pattern_desc[j].mask_length); - index += pkt_filter_elem.pattern_desc[j].mask_length; - memcpy(&p[index], pkt_filter_elem.pattern_desc[j].pattern, pkt_filter_elem.pattern_desc[j].mask_length); - index += pkt_filter_elem.pattern_desc[j].mask_length; - } - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_packet_filter_req(vif:%d, num_filters:%d)\n", ndev_vif->ifnum, num_filters); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_PACKET_FILTER_CFM); - if (!cfm) - return -EIO; - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_set_pmk(struct slsi_dev *sdev, struct net_device *dev, const u8 *pmk, u16 pmklen) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - if (pmk) - req = fapi_alloc(mlme_set_pmk_req, MLME_SET_PMK_REQ, ndev_vif->ifnum, pmklen); - else - req = fapi_alloc(mlme_set_pmk_req, MLME_SET_PMK_REQ, ndev_vif->ifnum, 0); - - if (!req) - return -ENOMEM; - if (pmk) - fapi_append_data(req, pmk, pmklen); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_pmk_req(vif:%u, pmklen:%d)\n", ndev_vif->ifnum, pmklen); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_PMK_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_pmk_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_pmk_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_pmk_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_roam(struct slsi_dev *sdev, struct net_device *dev, const u8 *bssid, u16 freq) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_roam_req(vif:%u, bssid:%pM, freq:%d)\n", ndev_vif->ifnum, bssid, freq); - req = fapi_alloc(mlme_roam_req, MLME_ROAM_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - fapi_set_memcpy(req, u.mlme_roam_req.bssid, bssid); - fapi_set_u16(req, u.mlme_roam_req.channel_frequency, SLSI_FREQ_HOST_TO_FW(freq)); - atomic_set(&ndev_vif->sta.drop_roamed_ind, 1); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ROAM_CFM); - atomic_set(&ndev_vif->sta.drop_roamed_ind, 0); - if (!cfm) - return -EIO; - if (fapi_get_u16(cfm, u.mlme_roam_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_roam_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_roam_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - ndev_vif->sta.roam_in_progress = true; - return r; -} - -int slsi_mlme_set_cached_channels(struct slsi_dev *sdev, struct net_device *dev, u32 channels_count, u8 *channels) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - u8 *p; - int r = 0; - size_t channel_ie = 0; - int i; - const u8 channels_list_ie_header[] = { - 0xDD, /* Element ID: Vendor Specific */ - 0x05, /* Length: actual length will be updated later */ - 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */ - 0x01, /* OUI Type: Scan parameters */ - 0x02 /* OUI Subtype: channel list */ - }; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - - if (channels_count) { - channel_ie += 6 + (channels_count * SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE); - req = fapi_alloc(mlme_set_cached_channels_req, MLME_SET_CACHED_CHANNELS_REQ, ndev_vif->ifnum, channel_ie); - } else { - req = fapi_alloc(mlme_set_cached_channels_req, MLME_SET_CACHED_CHANNELS_REQ, ndev_vif->ifnum, 0); - } - if (!req) - return -ENOMEM; - - if (channels_count) { - u16 freq_fw_unit; - u8 *channels_list_ie = fapi_append_data(req, channels_list_ie_header, sizeof(channels_list_ie_header)); - - if (!channels_list_ie) { - SLSI_WARN(sdev, "channel list IE append failed\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - - for (i = 0; i < channels_count; i++) { - SLSI_NET_DBG3(dev, SLSI_MLME, "request for channels %d\n", channels[i]); - p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE); - if (!p) { - slsi_kfree_skb(req); - return -EINVAL; - } - freq_fw_unit = 2 * ieee80211_channel_to_frequency(channels[i], (channels[i] <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ); - freq_fw_unit = cpu_to_le16(freq_fw_unit); - memcpy(p, &freq_fw_unit, sizeof(freq_fw_unit)); - - p[2] = FAPI_SCANPOLICY_2_4GHZ | FAPI_SCANPOLICY_5GHZ; - - channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE; - } - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_cached_channels_req(vif:%d)\n", ndev_vif->ifnum); - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CACHED_CHANNELS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_cached_channels_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_cached_channels_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_cached_channels_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_mlme_set_acl(struct slsi_dev *sdev, struct net_device *dev, u16 ifnum, const struct cfg80211_acl_data *params) -{ - struct sk_buff *req; - struct sk_buff *cfm; - size_t mac_acl_size = 0; - int i, r = 0; - - mac_acl_size = sizeof((params->mac_addrs[0])) * (params->n_acl_entries); - req = fapi_alloc(mlme_set_acl_req, MLME_SET_ACL_REQ, ifnum, mac_acl_size); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - fapi_set_u16(req, u.mlme_set_acl_req.entries, params->n_acl_entries); - fapi_set_u16(req, u.mlme_set_acl_req.acl_policy, params->acl_policy); - - for (i = 0; i < params->n_acl_entries; i++) - fapi_append_data(req, params->mac_addrs[i].addr, sizeof((params->mac_addrs[i]))); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_acl_req(vif:%u, n_acl_entries:%d)\n", ifnum, params->n_acl_entries); - - if (ifnum) - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_ACL_CFM); - else - cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_SET_ACL_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_acl_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_acl_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_acl_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} -#endif - -int slsi_mlme_set_traffic_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 user_priority, u16 medium_time, u16 minimun_data_rate, u8 *mac) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION && ndev_vif->iftype == NL80211_IFTYPE_STATION)) - return -EINVAL; - - req = fapi_alloc(mlme_set_traffic_parameters_req, MLME_SET_TRAFFIC_PARAMETERS_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_set_traffic_parameters_req.user_priority, user_priority); - fapi_set_u16(req, u.mlme_set_traffic_parameters_req.medium_time, medium_time); - fapi_set_u16(req, u.mlme_set_traffic_parameters_req.minimum_data_rate, minimun_data_rate); - - if (mac) - fapi_set_memcpy(req, u.mlme_set_traffic_parameters_req.peer_address, mac); - else - fapi_set_memset(req, u.mlme_set_traffic_parameters_req.peer_address, 0); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_traffic_parameters_req(vif:%u, user_priority:%d, medium_time:%d)\n", ndev_vif->ifnum, user_priority, medium_time); - rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_TRAFFIC_PARAMETERS_CFM); - if (!rx) - return -EIO; - - if (fapi_get_u16(rx, u.mlme_set_traffic_parameters_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_traffic_parameters_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_set_traffic_parameters_cfm.result_code)); - r = -EINVAL; - } - - return r; -} - -int slsi_mlme_del_traffic_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 user_priority) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION && ndev_vif->iftype == NL80211_IFTYPE_STATION)) - return -EINVAL; - - req = fapi_alloc(mlme_del_traffic_parameters_req, MLME_DEL_TRAFFIC_PARAMETERS_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_del_traffic_parameters_req.user_priority, user_priority); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_del_traffic_parameters_req(vif:%u, user_priority:%d)\n", ndev_vif->ifnum, user_priority); - rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_DEL_TRAFFIC_PARAMETERS_CFM); - if (!rx) - return -EIO; - - if (fapi_get_u16(rx, u.mlme_del_traffic_parameters_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_del_traffic_parameters_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_del_traffic_parameters_cfm.result_code)); - r = -EINVAL; - } - - return r; -} - -int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, struct slsi_mib_value *mib_val) -{ - struct slsi_mib_data mib_data = { 0, NULL }; - int error = 0; - - error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, mib_val->u.octetValue.dataLength, mib_val->u.octetValue.data, 0); - if (error != SLSI_MIB_STATUS_SUCCESS) { - error = -ENOMEM; - goto exit; - } - - if (WARN_ON(mib_data.dataLength == 0)) { - error = -EINVAL; - goto exit; - } - - error = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - kfree(mib_data.data); - - if (!error) - return 0; - -exit: - SLSI_ERR(sdev, "Error in setting ext capab. error = %d\n", error); - return error; -} - -int slsi_mlme_set_hs2_ext_cap(struct slsi_dev *sdev, struct net_device *dev, const u8 *ies, int ie_len) -{ - struct slsi_mib_entry mib_entry; - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_data mibrsp = { 0, NULL }; - const u8 *ext_capab_ie; - int r = 0; - int rx_length = 0; - int len = 0; - - slsi_mib_encode_get(&mibreq, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, 0); - - /* 5 (header) + 9 (data) + 2 (mlme expects 16 (??))*/ - mibrsp.dataLength = 16; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - - if (!mibrsp.data) { - SLSI_ERR(sdev, "Failed to alloc for Mib response\n"); - kfree(mibreq.data); - return -ENOMEM; - } - - r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength, - mibrsp.data, mibrsp.dataLength, &rx_length); - kfree(mibreq.data); - - if (r == 0) { - mibrsp.dataLength = rx_length; - len = slsi_mib_decode(&mibrsp, &mib_entry); - if (len == 0) { - SLSI_ERR(sdev, "Mib decode error\n"); - r = -EINVAL; - goto exit; - } - } else { - SLSI_NET_DBG1(dev, SLSI_MLME, "Mib read failed (error: %d)\n", r); - goto exit; - } - - ext_capab_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ie_len); - - if (ext_capab_ie) { - u8 ext_capab_ie_len = ext_capab_ie[1]; - - ext_capab_ie += 2; /* skip the EID and length*/ - - /*BSS Transition bit is bit 19 ,ie length must be >= 3 */ - if ((ext_capab_ie_len >= 3) && (ext_capab_ie[2] & SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED)) - mib_entry.value.u.octetValue.data[2] |= SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED; - else - mib_entry.value.u.octetValue.data[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED; - - /*interworking bit is bit 31 ,ie length must be >= 4 */ - if ((ext_capab_ie_len >= 4) && (ext_capab_ie[3] & SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED)) - mib_entry.value.u.octetValue.data[3] |= SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED; - else - mib_entry.value.u.octetValue.data[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED; - - /*QoS MAP is bit 32 ,ie length must be >= 5 */ - if ((ext_capab_ie_len >= 5) && (ext_capab_ie[4] & SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED)) - mib_entry.value.u.octetValue.data[4] |= SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED; - else - mib_entry.value.u.octetValue.data[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED; - - /*WNM- Notification bit is bit 46 ,ie length must be >= 6 */ - if ((ext_capab_ie_len >= 6) && (ext_capab_ie[5] & SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED)) - mib_entry.value.u.octetValue.data[5] |= SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED; - else - mib_entry.value.u.octetValue.data[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED; - } else { - mib_entry.value.u.octetValue.data[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED; - mib_entry.value.u.octetValue.data[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED; - mib_entry.value.u.octetValue.data[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED; - mib_entry.value.u.octetValue.data[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED; - } - - r = slsi_mlme_set_ext_capab(sdev, dev, &mib_entry.value); -exit: - kfree(mibrsp.data); - return r; -} - -int slsi_mlme_tdls_peer_resp(struct slsi_dev *sdev, struct net_device *dev, u16 pid, u16 tdls_event) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - - req = fapi_alloc(mlme_tdls_peer_res, MLME_TDLS_PEER_RES, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_tdls_peer_res.peer_index, pid); - fapi_set_u16(req, u.mlme_tdls_peer_res.tdls_event, tdls_event); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_tdls_peer_res(vif:%d)\n", ndev_vif->ifnum); - cfm = slsi_mlme_req_no_cfm(sdev, dev, req); - WARN_ON(cfm); - - return 0; -} - -int slsi_mlme_tdls_action(struct slsi_dev *sdev, struct net_device *dev, const u8 *peer, int action, u16 center_freq, u16 chan_info) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_tdls_action_req(action:%u)\n", action); - req = fapi_alloc(mlme_tdls_action_req, MLME_TDLS_ACTION_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - center_freq = SLSI_FREQ_HOST_TO_FW(center_freq); - - fapi_set_memcpy(req, u.mlme_tdls_action_req.peer_sta_address, peer); - fapi_set_u16(req, u.mlme_tdls_action_req.tdls_action, action); - fapi_set_u16(req, u.mlme_tdls_action_req.channel_frequency, center_freq); - fapi_set_u16(req, u.mlme_tdls_action_req.channel_information, chan_info); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_TDLS_ACTION_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_tdls_action_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_tdls_action_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_tdls_action_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - - return r; -} - -int slsi_mlme_reassociate(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - if (WARN_ON(!ndev_vif->activated)) - return -EINVAL; - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_reassoc_req(vif:%u)\n", ndev_vif->ifnum); - req = fapi_alloc(mlme_reassociate_req, MLME_REASSOCIATE_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_REASSOCIATE_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_reassociate_cfm.result_code) == FAPI_RESULTCODE_HOST_REQUEST_SUCCESS) { - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_reassoc_cfm(result:0x%04x)\n", - fapi_get_u16(cfm, u.mlme_reassociate_cfm.result_code)); - } else { - SLSI_NET_ERR(dev, "mlme_reassoc_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_reassociate_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - return r; -} - -void slsi_mlme_reassociate_resp(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_REASSOCIATE_RESP\n"); - return; - } - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_reassociate_resp(vif:%d)\n", ndev_vif->ifnum); - req = fapi_alloc(mlme_reassociate_res, MLME_REASSOCIATE_RES, ndev_vif->ifnum, 0); - if (!req) - return; - - cfm = slsi_mlme_req_no_cfm(sdev, dev, req); - WARN_ON(cfm); -} - -int slsi_mlme_add_range_req(struct slsi_dev *sdev, u8 count, - struct slsi_rtt_config *nl_rtt_params, u16 rtt_id, u16 vif_idx, u8 *source_addr) -{ - struct sk_buff *req; - struct sk_buff *rx; - int r = 0, i; - size_t alloc_data_size = 0; - u8 fapi_ie_generic[] = { 0xdd, 0x1c, 0x00, 0x16, 0x32, 0x0a, 0x01 }; - /* calculate data size */ - alloc_data_size += count * (fapi_ie_generic[1] + 2); - - req = fapi_alloc(mlme_add_range_req, MLME_ADD_RANGE_REQ, 0, alloc_data_size); - if (!req) { - SLSI_ERR(sdev, "failed to alloc %zd\n", alloc_data_size); - return -ENOMEM; - } - SLSI_DBG2(sdev, SLSI_MLME, "count:%d allocated data size: %d, source_addr:%pM\n", - count, alloc_data_size, source_addr); - /*fill the data */ - fapi_set_u16(req, u.mlme_add_range_req.vif, vif_idx); - fapi_set_u16(req, u.mlme_add_range_req.rtt_id, rtt_id); - fapi_set_memcpy(req, u.mlme_add_range_req.device_address, source_addr); - for (i = 0; i < count; i++) { - fapi_append_data(req, fapi_ie_generic, sizeof(fapi_ie_generic)); - fapi_append_data(req, nl_rtt_params[i].peer_addr, ETH_ALEN); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].type, 2); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].channel_freq, 2); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].burst_period, 1); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_burst, 1); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_frames_per_burst, 1); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_retries_per_ftmr, 1); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].burst_duration, 1); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].preamble, 2); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].bw, 2); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].LCI_request, 2); - fapi_append_data(req, (u8 *)&nl_rtt_params[i].LCR_request, 2); - } - rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_ADD_RANGE_CFM); - SLSI_DBG2(sdev, SLSI_MLME, "(After mlme req cfm for rtt config)\n"); - if (!rx) - return -EIO; - if (fapi_get_u16(rx, u.mlme_add_range_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_ERR(sdev, "mlme_add_range_cfm(ERROR:0x%04x)", - fapi_get_u16(rx, u.mlme_add_range_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(rx); - return r; -} - -bool slsi_del_range_cfm_validate(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm) -{ - int result = fapi_get_u16(cfm, u.mlme_del_range_cfm.result_code); - bool r = false; - - SLSI_UNUSED_PARAMETER(sdev); - - if (WARN_ON(!dev)) - goto exit; - - if (result == FAPI_RESULTCODE_SUCCESS) - r = true; - else - SLSI_NET_ERR(dev, "mlme_del_range_cfm(result:0x%04x) ERROR\n", result); - -exit: - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_del_range_req(struct slsi_dev *sdev, struct net_device *dev, u16 count, - u8 *addr, u16 rtt_id) -{ - struct sk_buff *req; - struct sk_buff *rx; - u16 *rtt_vif_idx = sdev->rtt_vif; - int r = 0, i; - size_t alloc_data_size = 0; - - /* calculate data size-->2 bytes for vif */ - alloc_data_size += count * sizeof(ETH_ALEN); - /* Alloc data size */ - req = fapi_alloc(mlme_del_range_req, MLME_DEL_RANGE_REQ, 0, alloc_data_size); - if (!req) { - SLSI_ERR(sdev, "failed to alloc %zd\n", alloc_data_size); - return -ENOMEM; - } - /*fill the data */ - fapi_set_u16(req, u.mlme_del_range_req.vif, rtt_vif_idx[rtt_id]); - fapi_set_u16(req, u.mlme_del_range_req.rtt_id, rtt_id); - fapi_set_u16(req, u.mlme_del_range_req.entries, count); - for (i = 0; i < count; i++) - fapi_append_data(req, &addr[i * ETH_ALEN], ETH_ALEN); - - rx = slsi_mlme_req_cfm_ind(sdev, dev, req, MLME_DEL_RANGE_CFM, MLME_RANGE_IND, slsi_del_range_cfm_validate); - sdev->rtt_vif[rtt_id] = -1; - if (!rx) { - SLSI_NET_ERR(dev, "mlme_del_range_cfm() ERROR\n"); - slsi_kfree_skb(rx); - return -EINVAL; - } - slsi_kfree_skb(rx); - return r; -} - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE -#define SLSI_FAPI_EPNO_NETWORK_MIN_SIZE (3) -int slsi_mlme_set_pno_list(struct slsi_dev *sdev, int count, - struct slsi_epno_param *epno_param, struct slsi_epno_hs2_param *epno_hs2_param) -{ - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - size_t alloc_data_size = 0; - u32 i, j; - u8 fapi_ie_generic[] = { 0xdd, 0, 0x00, 0x16, 0x32, 0x01, 0x00 }; - u8 *buff_ptr, *ie_start_pos; - - if (count) { - /* calculate data size */ - if (epno_param) { - alloc_data_size += sizeof(fapi_ie_generic) + SLSI_FAPI_EPNO_NETWORK_MIN_SIZE * count + 11; - for (i = 0; i < count; i++) - alloc_data_size += epno_param->epno_ssid[i].ssid_len; - } else if (epno_hs2_param) { - for (i = 0; i < count; i++) { - /* fapi_ie_generic + Network_block_ID(1) + Realm_length(1) + realm_data(x) - * + Roaming_Consortium_Count(1) + Roaming Consortium data(16 * 8) + - * PLMN length(1) + PLMN data(6) - */ - if (strlen(epno_hs2_param->realm)) - alloc_data_size += sizeof(fapi_ie_generic) + 1 + 1 + (strlen(epno_hs2_param->realm) + 1) - + 1 + 16 * 8 + 1 + 6; - else - alloc_data_size += sizeof(fapi_ie_generic) + 1 + 1 + 0 - + 1 + 16 * 8 + 1 + 6; - } - } - } - - /* Alloc data size */ - req = fapi_alloc(mlme_set_pno_list_req, MLME_SET_PNO_LIST_REQ, 0, alloc_data_size); - if (!req) { - SLSI_ERR(sdev, "failed to alloc %zd\n", alloc_data_size); - return -ENOMEM; - } - if (count) { - /* Fill data */ - if (epno_param) { - fapi_ie_generic[1] = alloc_data_size - 2; - fapi_ie_generic[6] = 9; /* OUI */ - fapi_append_data(req, fapi_ie_generic, sizeof(fapi_ie_generic)); - fapi_append_data(req, (u8 *)epno_param, (sizeof(*epno_param) - 1)); - for (i = 0; i < count; i++) { - fapi_append_data(req, (u8 *)&epno_param->epno_ssid[i].flags, 2); - fapi_append_data(req, (u8 *)&epno_param->epno_ssid[i].ssid_len, 1); - fapi_append_data(req, (u8 *)epno_param->epno_ssid[i].ssid, - epno_param->epno_ssid[i].ssid_len); - } - } else if (epno_hs2_param) { - u8 realm_length; - u8 roaming_consortium_count = 16; - u8 plmn_length = 6; - u8 plmn_digit[6]; - - fapi_ie_generic[6] = 0x10; /* OUI subtype = Passpoint Network */ - for (i = 0; i < count; i++) { - buff_ptr = fapi_append_data(req, fapi_ie_generic, sizeof(fapi_ie_generic)); - if (!buff_ptr) { - SLSI_ERR(sdev, "failed append data\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - ie_start_pos = buff_ptr; - - fapi_append_data(req, (u8 *)&epno_hs2_param[i].id, 1); - - realm_length = strlen(epno_hs2_param[i].realm); - if (realm_length) { - realm_length++; - fapi_append_data(req, &realm_length, 1); - fapi_append_data(req, epno_hs2_param[i].realm, realm_length); - } else { - fapi_append_data(req, &realm_length, 1); - } - - fapi_append_data(req, &roaming_consortium_count, 1); - fapi_append_data(req, (u8 *)&epno_hs2_param[i].roaming_consortium_ids, 16 * 8); - - fapi_append_data(req, &plmn_length, 1); - for (j = 0; j < 3; j++) { - plmn_digit[j * 2] = epno_hs2_param[i].plmn[i] & 0x0F; - plmn_digit[(j * 2) + 1] = epno_hs2_param[i].plmn[i] & 0xF0 >> 4; - } - buff_ptr = fapi_append_data(req, plmn_digit, sizeof(plmn_digit)); - if (!buff_ptr) { - SLSI_ERR(sdev, "failed append data\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - - buff_ptr += sizeof(plmn_digit); - ie_start_pos[1] = buff_ptr - ie_start_pos - 2; /* fill ie length field */ - } - } - } - - /* Send signal */ - /* Use the Global sig_wait not the Interface specific for mlme-set-pno.list */ - rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_SET_PNO_LIST_CFM); - if (!rx) - return -EIO; - if (fapi_get_u16(rx, u.mlme_set_pno_list_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_ERR(sdev, "mlme_set_pno_list_cfm(ERROR:0x%04x)", - fapi_get_u16(rx, u.mlme_set_pno_list_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(rx); - return r; -} - -int slsi_mlme_start_link_stats_req(struct slsi_dev *sdev, u16 mpdu_size_threshold, bool aggressive_stats_enabled) -{ - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - req = fapi_alloc(mlme_start_link_statistics_req, MLME_START_LINK_STATISTICS_REQ, 0, 0); - if (!req) { - SLSI_ERR(sdev, "memory allocation failed for signal\n"); - return -ENOMEM; - } - - fapi_set_u16(req, u.mlme_start_link_statistics_req.mpdu_size_threshold, mpdu_size_threshold); - fapi_set_u16(req, u.mlme_start_link_statistics_req.aggressive_statistics_gathering_enabled, - aggressive_stats_enabled); - - SLSI_DBG2(sdev, SLSI_MLME, "(mpdu_size_threshold:%d, aggressive_stats_enabled:%d)\n", - mpdu_size_threshold, aggressive_stats_enabled); - cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_START_LINK_STATISTICS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_start_link_statistics_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_ERR(sdev, "mlme_start_link_statistics_cfm (result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_start_link_statistics_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_stop_link_stats_req(struct slsi_dev *sdev, u16 stats_stop_mask) -{ - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - req = fapi_alloc(mlme_stop_link_statistics_req, MLME_STOP_LINK_STATISTICS_REQ, 0, 0); - if (!req) { - SLSI_ERR(sdev, "memory allocation failed for signal\n"); - return -ENOMEM; - } - - fapi_set_u16(req, u.mlme_stop_link_statistics_req.statistics_stop_bitmap, stats_stop_mask); - - SLSI_DBG2(sdev, SLSI_MLME, "statistics_stop_bitmap:%d\n", stats_stop_mask); - cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_STOP_LINK_STATISTICS_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_stop_link_statistics_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_ERR(sdev, "mlme_stop_link_statistics_cfm (result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_stop_link_statistics_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - return r; -} -#endif - -int slsi_mlme_set_rssi_monitor(struct slsi_dev *sdev, struct net_device *dev, u8 enable, s8 low_rssi_threshold, s8 high_rssi_threshold) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_rssi_monitor(vif:%u), enable =%d, low_rssi_threshold = %d,high_rssi_threshold =%d\n", - ndev_vif->ifnum, enable, low_rssi_threshold, high_rssi_threshold); - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - req = fapi_alloc(mlme_monitor_rssi_req, MLME_MONITOR_RSSI_REQ, ndev_vif->ifnum, 0); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - fapi_set_u16(req, u.mlme_monitor_rssi_req.rssi_monitoring_enabled, enable); - fapi_set_u16(req, u.mlme_monitor_rssi_req.low_rssi_threshold, low_rssi_threshold); - fapi_set_u16(req, u.mlme_monitor_rssi_req.high_rssi_threshold, high_rssi_threshold); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_MONITOR_RSSI_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_monitor_rssi_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_monitor_rssi_cfm(result:0x%04x) ERROR\n", fapi_get_u16(cfm, u.mlme_monitor_rssi_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -struct slsi_mib_value *slsi_read_mibs(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_mib_get_entry *mib_entries, int mib_count, struct slsi_mib_data *mibrsp) -{ - struct slsi_mib_data mibreq = { 0, NULL }; - struct slsi_mib_value *values; - int rx_length, r; - - r = slsi_mib_encode_get_list(&mibreq, mib_count, mib_entries); - if (r != SLSI_MIB_STATUS_SUCCESS) { - SLSI_WARN(sdev, "slsi_mib_encode_get_list fail %d\n", r); - return NULL; - } - - r = slsi_mlme_get(sdev, dev, mibreq.data, mibreq.dataLength, mibrsp->data, mibrsp->dataLength, &rx_length); - kfree(mibreq.data); - - if (r != 0) { - SLSI_ERR(sdev, "Mib (err:%d)\n", r); - return NULL; - } - - mibrsp->dataLength = (u32)rx_length; - values = slsi_mib_decode_get_list(mibrsp, mib_count, mib_entries); - if (!values) - SLSI_WARN(sdev, "decode error\n"); - return values; -} - -int slsi_mlme_set_ctwindow(struct slsi_dev *sdev, struct net_device *dev, unsigned int ct_param) -{ - struct netdev_vif *ndev_vif; - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_ctwindow(ct_param = %d)\n", ct_param); - - ndev_vif = netdev_priv(dev); - - req = fapi_alloc(mlme_set_ctwindow_req, MLME_SET_CTWINDOW_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_set_ctwindow_req.ctwindow, ct_param); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CTWINDOW_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_ctwindow_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_ctwindow_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_ctwindow_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_set_p2p_noa(struct slsi_dev *sdev, struct net_device *dev, unsigned int noa_count, - unsigned int interval, unsigned int duration) -{ - struct netdev_vif *ndev_vif; - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_noa_req(noa_count = %d, interval = %d, duration = %d)\n", - noa_count, interval, duration); - - ndev_vif = netdev_priv(dev); - - req = fapi_alloc(mlme_set_noa_req, MLME_SET_NOA_REQ, ndev_vif->ifnum, 0); - if (!req) - return -ENOMEM; - - fapi_set_u16(req, u.mlme_set_noa_req.request_id, SLSI_NOA_CONFIG_REQUEST_ID); - fapi_set_u16(req, u.mlme_set_noa_req.noa_count, noa_count); - if (!interval) - fapi_set_u32(req, u.mlme_set_noa_req.interval, (1 * 1024 * ndev_vif->ap.beacon_interval)); - else - fapi_set_u32(req, u.mlme_set_noa_req.interval, interval * 1000); - fapi_set_u32(req, u.mlme_set_noa_req.duration, duration * 1000); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_NOA_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_set_noa_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_set_noa_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_set_noa_cfm.result_code)); - r = -EINVAL; - } - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_set_host_state(struct slsi_dev *sdev, struct net_device *dev, u8 host_state) -{ - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_INFO(dev, "Skip MLME_HOST_STATE_REQ in wlanlite mode\n"); - return -EOPNOTSUPP; - } - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_host_state(state =%d)\n", host_state); - - req = fapi_alloc(mlme_host_state_req, MLME_HOST_STATE_REQ, 0, 0); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - fapi_set_u16(req, u.mlme_host_state_req.host_state, host_state); - - cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_HOST_STATE_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_host_state_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -int slsi_mlme_read_apf_request(struct slsi_dev *sdev, struct net_device *dev, u8 **host_dst, int *datalen) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - SLSI_ERR(sdev, "ndev_vif is not activated\n"); - r = -EINVAL; - goto exit; - } - - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) { - SLSI_ERR(sdev, "vif_type is not FAPI_VIFTYPE_STATION\n"); - r = -EINVAL; - goto exit; - } - - req = fapi_alloc(mlme_read_apf_req, MLME_READ_APF_REQ, ndev_vif->ifnum, 0); - if (!req) { - r = -ENOMEM; - goto exit; - } - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_read_apf_req(vif:%u)\n", ndev_vif->ifnum); - rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_READ_APF_CFM); - if (!rx) { - r = -EIO; - goto exit; - } - - if (fapi_get_u16(rx, u.mlme_read_apf_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_read_apf_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_read_apf_cfm.result_code)); - r = -EINVAL; - } - - *datalen = fapi_get_datalen(rx); - *host_dst = fapi_get_data(rx); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -int slsi_mlme_install_apf_request(struct slsi_dev *sdev, struct net_device *dev, - u8 *program, u32 program_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - SLSI_ERR(sdev, "ndev_vif is not activated\n"); - r = -EINVAL; - goto exit; - } - - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) { - SLSI_ERR(sdev, "vif_type is not FAPI_VIFTYPE_STATION\n"); - r = -EINVAL; - goto exit; - } - - req = fapi_alloc(mlme_install_apf_req, MLME_INSTALL_APF_REQ, ndev_vif->ifnum, program_len); - if (!req) { - r = -ENOMEM; - goto exit; - } - - /* filter_mode will be "don't care" for FW */ - fapi_set_u16(req, u.mlme_install_apf_req.filter_mode, FAPI_APFFILTERMODE_SUSPEND); - fapi_append_data(req, program, program_len); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_install_apf_req(vif:%u, filter_mode:%d)\n", - ndev_vif->ifnum, FAPI_APFFILTERMODE_SUSPEND); - rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_INSTALL_APF_CFM); - if (!rx) { - r = -EIO; - goto exit; - } - - if (fapi_get_u16(rx, u.mlme_install_apf_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_install_apf_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_install_apf_cfm.result_code)); - r = -EINVAL; - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -int slsi_mlme_arp_detect_request(struct slsi_dev *sdev, struct net_device *dev, u16 action, u8 *target_ipaddr) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *rx; - int r = 0; - u32 ipaddress = 0x0; - int i = 0; - - if (!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)) { - SLSI_ERR(sdev, "ndev_vif mutex is not locked\n"); - r = -EINVAL; - goto exit; - } - - if (!ndev_vif->activated) { - SLSI_ERR(sdev, "ndev_vif is not activated\n"); - r = -EINVAL; - goto exit; - } - - if ((ndev_vif->vif_type != FAPI_VIFTYPE_STATION) && (ndev_vif->iftype == NL80211_IFTYPE_STATION)) { - SLSI_ERR(sdev, "vif_type is not FAPI_VIFTYPE_STATION\n"); - r = -EINVAL; - goto exit; - } - - req = fapi_alloc(mlme_arp_detect_req, MLME_ARP_DETECT_REQ, ndev_vif->ifnum, 0); - if (!req) { - r = -ENOMEM; - goto exit; - } - - for (i = 0; i < 4; i++) - ipaddress = (ipaddress << 8) | ((unsigned char)target_ipaddr[i]); - ipaddress = htonl(ipaddress); - - fapi_set_u16(req, u.mlme_arp_detect_req.arp_detect_action, action); - fapi_append_data(req, (const u8 *)&ipaddress, 4); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_arp_detect_req(vif:%u, action:%d IP Address:%d.%d.%d.%d)\n", - ndev_vif->ifnum, action, ndev_vif->target_ip_addr[0], ndev_vif->target_ip_addr[1], - ndev_vif->target_ip_addr[2], ndev_vif->target_ip_addr[3]); - rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_ARP_DETECT_CFM); - if (!rx) { - r = -EIO; - goto exit; - } - - if (fapi_get_u16(rx, u.mlme_arp_detect_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "mlme_arp_detect_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(rx, u.mlme_arp_detect_cfm.result_code)); - r = -EINVAL; - } - -exit: - return r; -} -#endif - -#ifdef CONFIG_SCSC_WLAN_DEBUG -#define SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE (12) -int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - u8 *p = NULL; - size_t alloc_data_size = 0; - u16 center_freq1; - u16 center_freq2; - u16 chan_info; - int r = 0; - - const u8 monitor_config_ie_header[] = { - 0xDD, /* Element ID: Vendor Specific */ - 0x11, /* Length */ - 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */ - 0x10, /* OUI Type: Monitor mode parameters */ - 0x01 /* OUI Subtype: configuration */ - }; - - if (slsi_is_test_mode_enabled()) { - SLSI_NET_WARN(dev, "WlanLite: NOT supported\n"); - return -EOPNOTSUPP; - } - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - - chan_info = slsi_get_chann_info(sdev, chandef); - SLSI_NET_DBG2(dev, SLSI_MLME, "test_configure_monitor_mode_req(center_freq1:%u, chan_info:%u, center_freq2:%u)\n", - chandef->center_freq1, - chan_info, - chandef->center_freq2); - - center_freq1 = SLSI_FREQ_HOST_TO_FW(chandef->center_freq1); - center_freq1 = cpu_to_le16(center_freq1); - center_freq2 = SLSI_FREQ_HOST_TO_FW(chandef->center_freq2); - center_freq2 = cpu_to_le16(center_freq2); - - alloc_data_size = sizeof(monitor_config_ie_header) + SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE; - - req = fapi_alloc(test_configure_monitor_mode_req, TEST_CONFIGURE_MONITOR_MODE_REQ, ndev_vif->ifnum, alloc_data_size); - if (!req) { - SLSI_NET_ERR(dev, "failed to alloc Monitor mode request (len:%d)\n", alloc_data_size); - return -ENOMEM; - } - - fapi_append_data(req, monitor_config_ie_header, sizeof(monitor_config_ie_header)); - fapi_append_data(req, (const u8 *)¢er_freq1, 2); - fapi_append_data(req, (const u8 *)&chan_info, 2); - p = fapi_append_data(req, (const u8 *)¢er_freq2, 2); - - /* MAC address filtering is not supported yet; so fill in zeros */ - memset(p, 0, 6); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, TEST_CONFIGURE_MONITOR_MODE_CFM); - if (!cfm) { - SLSI_NET_ERR(dev, "failed to receive Confirm\n"); - return -EIO; - } - - if (fapi_get_u16(cfm, u.mlme_set_channel_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "test_configure_monitor_mode_cfm(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.test_configure_monitor_mode_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -#endif diff --git a/drivers/net/wireless/scsc/mlme.h b/drivers/net/wireless/scsc/mlme.h deleted file mode 100755 index 9a08f56b9719..000000000000 --- a/drivers/net/wireless/scsc/mlme.h +++ /dev/null @@ -1,281 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_MLME_H__ -#define __SLSI_MLME_H__ - -#include "dev.h" -#include "mib.h" - -enum slsi_ac_index_wmm_pe { - AC_BE, - AC_BK, - AC_VI, - AC_VO -}; - -#define SLSI_FREQ_FW_TO_HOST(f) ((f) / 2) -#define SLSI_FREQ_HOST_TO_FW(f) ((f) * 2) - -#define SLSI_SINFO_MIB_ACCESS_TIMEOUT (1000) /* 1 sec timeout */ - -#define SLSI_WLAN_EID_VENDOR_SPECIFIC 0xdd -#define SLSI_WLAN_EID_INTERWORKING 107 -#define SLSI_WLAN_EID_EXTENSION 255 - -#define SLSI_WLAN_OUI_TYPE_WFA_HS20_IND 0x10 -#define SLSI_WLAN_OUI_TYPE_WFA_OSEN 0x12 - -/*Extended capabilities bytes*/ -#define SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED (1 << 3) -#define SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED (1 << 7) -#define SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED (1 << 0) -#define SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED (1 << 6) -#define SLSI_WLAN_EXT_CAPA2_QBSS_LOAD_ENABLED BIT(7) -#define SLSI_WLAN_EXT_CAPA1_PROXY_ARP_ENABLED BIT(4) -#define SLSI_WLAN_EXT_CAPA2_TFS_ENABLED BIT(0) -#define SLSI_WLAN_EXT_CAPA2_WNM_SLEEP_ENABLED BIT(1) -#define SLSI_WLAN_EXT_CAPA2_TIM_ENABLED BIT(2) -#define SLSI_WLAN_EXT_CAPA2_DMS_ENABLED BIT(4) - -/*RM Enabled Capabilities Bytes*/ -#define SLSI_WLAN_RM_CAPA0_LINK_MEASUREMENT_ENABLED BIT(0) -#define SLSI_WLAN_RM_CAPA0_NEIGHBOR_REPORT_ENABLED BIT(1) -#define SLSI_WLAN_RM_CAPA0_PASSIVE_MODE_ENABLED BIT(4) -#define SLSI_WLAN_RM_CAPA0_ACTIVE_MODE_ENABLED BIT(5) -#define SLSI_WLAN_RM_CAPA0_TABLE_MODE_ENABLED BIT(6) - - -#define SLSI_AP_EXT_CAPAB_IE_LEN_MAX 12 /* EID (1) + Len (1) + Ext Capab (8) */ - -#define SLSI_SCAN_DONE_IND_WAIT_TIMEOUT 40000 /* 40 seconds */ - -/* WLAN_EID_COUNTRY available from kernel version 3.7 */ -#ifndef WLAN_EID_COUNTRY -#define WLAN_EID_COUNTRY 7 -#endif - -/* P2P (Wi-Fi Direct) */ -#define SLSI_P2P_WILDCARD_SSID "DIRECT-" -#define SLSI_P2P_WILDCARD_SSID_LENGTH 7 -#define SLSI_P2P_SOCIAL_CHAN_COUNT 3 - -/* A join scan with P2P GO SSID can come and hence the SSID length comparision should include >= */ -#define SLSI_IS_P2P_SSID(ssid, ssid_len) ((ssid_len >= SLSI_P2P_WILDCARD_SSID_LENGTH) && \ - (memcmp(ssid, SLSI_P2P_WILDCARD_SSID, SLSI_P2P_WILDCARD_SSID_LENGTH) == 0)) - -/* Action frame categories for registering with firmware */ -#define SLSI_ACTION_FRAME_PUBLIC (1 << 4) -#define SLSI_ACTION_FRAME_VENDOR_SPEC_PROTECTED (1 << 30) -#define SLSI_ACTION_FRAME_VENDOR_SPEC (1 << 31) -#define SLSI_ACTION_FRAME_WMM (1 << 17) -#define SLSI_ACTION_FRAME_WNM (1 << 10) -#define SLSI_ACTION_FRAME_QOS (1 << 1) -#define SLSI_ACTION_FRAME_PROTECTED_DUAL BIT(9) -#define SLSI_ACTION_FRAME_RADIO_MEASUREMENT BIT(5) - -/* Firmware transmit rates */ -#define SLSI_TX_RATE_NON_HT_1MBPS 0x4001 -#define SLSI_TX_RATE_NON_HT_6MBPS 0x4004 -#define SLSI_ROAMING_CHANNELS_MAX 38 - -#define SLSI_WLAN_EID_WAPI 68 - -/** - * If availability_duration is set to SLSI_FW_CHANNEL_DURATION_UNSPECIFIED - * then the firmware autonomously decides how long to remain listening on - * the configured channel. - */ -#define SLSI_FW_CHANNEL_DURATION_UNSPECIFIED (0x0000) -extern struct ieee80211_supported_band slsi_band_2ghz; -extern struct ieee80211_supported_band slsi_band_5ghz; -extern struct ieee80211_sta_vht_cap slsi_vht_cap; - -/* Packet Filtering */ -#define SLSI_MAX_PATTERN_DESC 4 /* We are not using more than 4 pattern descriptors in a pkt filter*/ -#define SLSI_PKT_DESC_FIXED_LEN 2 /* offset (1) + mask length (1)*/ -#define SLSI_PKT_FILTER_ELEM_FIXED_LEN 6 /* oui(3) + oui type(1) + filter id (1) + pkt filter mode(1)*/ -#define SLSI_PKT_FILTER_ELEM_HDR_LEN (2 + SLSI_PKT_FILTER_ELEM_FIXED_LEN) /* element id + len + SLSI_PKT_FILTER_ELEM_FIXED_LEN*/ -#define SLSI_MAX_PATTERN_LENGTH 6 - -/*Default values of MIBS params for GET_STA_INFO driver private command */ -#define SLSI_DEFAULT_UNIFI_PEER_RX_RETRY_PACKETS 0 -#define SLSI_DEFAULT_UNIFI_PEER_RX_BC_MC_PACKETS 0 -#define SLSI_DEFAULT_UNIFI_PEER_BANDWIDTH -1 -#define SLSI_DEFAULT_UNIFI_PEER_NSS 0 -#define SLSI_DEFAULT_UNIFI_PEER_RSSI 1 -#define SLSI_DEFAULT_UNIFI_PEER_TX_DATA_RATE 0 - -#define SLSI_CHECK_TYPE(sdev, recv_type, exp_type) \ - do { \ - int var1 = recv_type; \ - int var2 = exp_type; \ - if (var1 != var2) { \ - SLSI_WARN(sdev, "Type mismatched, expected type: %d and received type %d ", var2, var1); \ - } \ - } while (0) - - -struct slsi_mlme_pattern_desc { - u8 offset; - u8 mask_length; - u8 mask[SLSI_MAX_PATTERN_LENGTH]; - u8 pattern[SLSI_MAX_PATTERN_LENGTH]; -}; - -struct slsi_mlme_pkt_filter_elem { - u8 header[SLSI_PKT_FILTER_ELEM_HDR_LEN]; - u8 num_pattern_desc; - struct slsi_mlme_pattern_desc pattern_desc[SLSI_MAX_PATTERN_DESC]; -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -u16 slsi_get_chann_info(struct slsi_dev *sdev, struct cfg80211_chan_def *chandef); -int slsi_check_channelization(struct slsi_dev *sdev, struct cfg80211_chan_def *chandef, - int wifi_sharing_channel_switched); -#else -u16 slsi_get_chann_info(struct slsi_dev *sdev, enum nl80211_channel_type channel_type); -int slsi_check_channelization(struct slsi_dev *sdev, enum nl80211_channel_type channel_type); -#endif - -int slsi_mlme_set_ip_address(struct slsi_dev *sdev, struct net_device *dev); -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 -int slsi_mlme_set_ipv6_address(struct slsi_dev *sdev, struct net_device *dev); -#endif -int slsi_mlme_set(struct slsi_dev *sdev, struct net_device *dev, u8 *req, int req_len); -int slsi_mlme_get(struct slsi_dev *sdev, struct net_device *dev, u8 *req, int req_len, - u8 *resp, int resp_buf_len, int *resp_len); - -int slsi_mlme_add_vif(struct slsi_dev *sdev, struct net_device *dev, u8 *interface_address, u8 *device_address); -void slsi_mlme_del_vif(struct slsi_dev *sdev, struct net_device *dev); -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -int slsi_mlme_set_forward_beacon(struct slsi_dev *sdev, struct net_device *dev, int action); -#endif -int slsi_mlme_set_channel(struct slsi_dev *sdev, struct net_device *dev, struct ieee80211_channel *chan, u16 duration, u16 interval, u16 count); -void slsi_ap_obss_scan_done_ind(struct net_device *dev, struct netdev_vif *ndev_vif); - -int slsi_mlme_unset_channel_req(struct slsi_dev *sdev, struct net_device *dev); - -u16 slsi_compute_chann_info(struct slsi_dev *sdev, u16 width, u16 center_freq0, u16 channel_freq); -/** - * slsi_mlme_add_autonomous_scan() Returns: - * 0 : Scan installed - * >0 : Scan NOT installed. Not an Error - * <0 : Scan NOT installed. Error - */ -int slsi_mlme_add_scan(struct slsi_dev *sdev, - struct net_device *dev, - u16 scan_type, - u16 report_mode, - u32 n_ssids, - struct cfg80211_ssid *ssids, - u32 n_channels, - struct ieee80211_channel *channels[], - void *gscan_param, - const u8 *ies, - u16 ies_len, - bool wait_for_ind); - -int slsi_mlme_add_sched_scan(struct slsi_dev *sdev, - struct net_device *dev, - struct cfg80211_sched_scan_request *request, - const u8 *ies, - u16 ies_len); - -int slsi_mlme_del_scan(struct slsi_dev *sdev, struct net_device *dev, u16 scan_id, bool scan_timed_out); -int slsi_mlme_start(struct slsi_dev *sdev, struct net_device *dev, u8 *bssid, struct cfg80211_ap_settings *settings, const u8 *wpa_ie_pos, const u8 *wmm_ie_pos, bool append_vht_ies); -int slsi_mlme_connect(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_connect_params *sme, struct ieee80211_channel *channel, const u8 *bssid); -int slsi_mlme_set_key(struct slsi_dev *sdev, struct net_device *dev, u16 key_id, u16 key_type, const u8 *address, struct key_params *key); -int slsi_mlme_get_key(struct slsi_dev *sdev, struct net_device *dev, u16 key_id, u16 key_type, u8 *seq, int *seq_len); - -/** - * Sends MLME-DISCONNECT-REQ and waits for the MLME-DISCONNECT-CFM - * MLME-DISCONNECT-CFM only indicates if the firmware has accepted the request (or not) - * the actual end of the disconnection is indicated by the firmware sending - * MLME-DISCONNECT-IND (following a successful MLME-DISCONNECT-CFM). - * The host has to wait for the full exchange to complete with the firmware before - * returning to cfg80211 if it made the disconnect request. Due to this, this function - * waits for both the MLME-DISCONNECT-CFM and the MLME-DISCONNECT-IND (if the - * MLME-DISCONNECT-CFM was successful) - */ -int slsi_mlme_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *bssid, u16 reason_code, bool wait_ind); - -int slsi_mlme_req(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -struct sk_buff *slsi_mlme_req_no_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); - -struct sk_buff *slsi_mlme_req_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 ind_id); -/* Reads multiple MIB data related to station info. returns 0 if success else errno*/ -int slsi_mlme_get_sinfo_mib(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_peer *peer); - -int slsi_mlme_connect_scan(struct slsi_dev *sdev, struct net_device *dev, - u32 n_ssids, struct cfg80211_ssid *ssids, struct ieee80211_channel *channel); -int slsi_mlme_powermgt(struct slsi_dev *sdev, struct net_device *dev, u16 ps_mode); -int slsi_mlme_powermgt_unlocked(struct slsi_dev *sdev, struct net_device *dev, u16 ps_mode); -int slsi_mlme_register_action_frame(struct slsi_dev *sdev, struct net_device *dev, u32 af_bitmap_active, u32 af_bitmap_suspended); -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG -int slsi_mlme_synchronised_response(struct slsi_dev *sdev, struct net_device *dev, - struct cfg80211_external_auth_params *params); -#endif -int slsi_mlme_channel_switch(struct slsi_dev *sdev, struct net_device *dev, u16 center_freq, u16 chan_info); -int slsi_mlme_add_info_elements(struct slsi_dev *sdev, struct net_device *dev, u16 purpose, const u8 *ies, const u16 ies_len); -int slsi_mlme_send_frame_mgmt(struct slsi_dev *sdev, struct net_device *dev, const u8 *frame, int frame_len, u16 data_desc, u16 msg_type, u16 host_tag, u16 freq, u32 dwell_time, u32 period); -int slsi_mlme_send_frame_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 msg_type, - u16 host_tag, u32 dwell_time, u32 period); -int slsi_mlme_reset_dwell_time(struct slsi_dev *sdev, struct net_device *dev); -int slsi_mlme_set_packet_filter(struct slsi_dev *sdev, struct net_device *dev, int pkt_filter_len, u8 num_filters, struct slsi_mlme_pkt_filter_elem *pkt_filter_elems); -void slsi_mlme_connect_resp(struct slsi_dev *sdev, struct net_device *dev); -void slsi_mlme_connected_resp(struct slsi_dev *sdev, struct net_device *dev, u16 peer_index); -void slsi_mlme_roamed_resp(struct slsi_dev *sdev, struct net_device *dev); -int slsi_mlme_set_pmk(struct slsi_dev *sdev, struct net_device *dev, const u8 *pmk, u16 pmklen); -int slsi_mlme_roam(struct slsi_dev *sdev, struct net_device *dev, const u8 *bssid, u16 freq); -int slsi_mlme_set_cached_channels(struct slsi_dev *sdev, struct net_device *dev, u32 channels_count, u8 *channels); -int slsi_mlme_tdls_peer_resp(struct slsi_dev *sdev, struct net_device *dev, u16 pid, u16 tdls_event); -int slsi_mlme_tdls_action(struct slsi_dev *sdev, struct net_device *dev, const u8 *peer, int action, u16 center_freq, u16 chan_info); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -int slsi_mlme_set_acl(struct slsi_dev *sdev, struct net_device *dev, u16 ifnum, const struct cfg80211_acl_data *params); -#endif -int slsi_mlme_set_traffic_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 user_priority, u16 medium_time, u16 minimun_data_rate, u8 *mac); -int slsi_mlme_del_traffic_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 user_priority); - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE -int slsi_mlme_set_pno_list(struct slsi_dev *sdev, int count, - struct slsi_epno_param *epno_param, struct slsi_epno_hs2_param *epno_hs2_param); -int slsi_mlme_start_link_stats_req(struct slsi_dev *sdev, u16 mpdu_size_threshold, bool aggressive_statis_enabled); -int slsi_mlme_stop_link_stats_req(struct slsi_dev *sdev, u16 stats_stop_mask); -int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req); -int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_publish_req *hal_req, - u16 publish_id); -int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_subscribe_req *hal_req, - u16 subscribe_id); -int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_hal_nan_transmit_followup_req *hal_req); -int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_config_req *hal_req); -#endif - -int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, struct slsi_mib_value *mib_val); -int slsi_mlme_set_hs2_ext_cap(struct slsi_dev *sdev, struct net_device *dev, const u8 *ies, int ie_len); -int slsi_mlme_reassociate(struct slsi_dev *sdev, struct net_device *dev); -void slsi_mlme_reassociate_resp(struct slsi_dev *sdev, struct net_device *dev); -int slsi_modify_ies(struct net_device *dev, u8 eid, u8 *ies, int ies_len, u8 ie_index, u8 ie_value); -int slsi_mlme_set_rssi_monitor(struct slsi_dev *sdev, struct net_device *dev, u8 enable, s8 low_rssi_threshold, s8 high_rssi_threshold); -struct slsi_mib_value *slsi_read_mibs(struct slsi_dev *sdev, struct net_device *dev, struct slsi_mib_get_entry *mib_entries, int mib_count, struct slsi_mib_data *mibrsp); -int slsi_mlme_set_host_state(struct slsi_dev *sdev, struct net_device *dev, u8 host_state); -int slsi_mlme_read_apf_request(struct slsi_dev *sdev, struct net_device *dev, u8 **host_dst, int *datalen); -int slsi_mlme_install_apf_request(struct slsi_dev *sdev, struct net_device *dev, - u8 *program, u32 program_len); -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT -int slsi_mlme_arp_detect_request(struct slsi_dev *sdev, struct net_device *dev, u16 action, u8 *ipaddr); -#endif -int slsi_mlme_set_ctwindow(struct slsi_dev *sdev, struct net_device *dev, unsigned int ct_param); -int slsi_mlme_set_p2p_noa(struct slsi_dev *sdev, struct net_device *dev, unsigned int noa_count, - unsigned int interval, unsigned int duration); -void slsi_decode_fw_rate(u16 fw_rate, struct rate_info *rate, unsigned long *data_rate_mbps); -int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef); - -struct sk_buff *slsi_mlme_req_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id); - -#endif /*__SLSI_MLME_H__*/ diff --git a/drivers/net/wireless/scsc/mlme_nan.c b/drivers/net/wireless/scsc/mlme_nan.c deleted file mode 100755 index b22459b4adc1..000000000000 --- a/drivers/net/wireless/scsc/mlme_nan.c +++ /dev/null @@ -1,797 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "debug.h" -#include "mlme.h" - -#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, val) \ - { \ - u16 attribute_len = 1; \ - struct sk_buff *req_p = req; \ - fapi_append_data((req_p), (u8 *)&(attribute), 2); \ - fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ - fapi_append_data((req_p), (u8 *)&(val), 1); \ - } - -#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, val) \ - { \ - u16 attribute_len = 2; \ - __le16 le16val = cpu_to_le16(val); \ - struct sk_buff *req_p = req; \ - fapi_append_data((req_p), (u8 *)&(attribute), 2); \ - fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ - fapi_append_data((req_p), (u8 *)&le16val, 2); \ - } - -#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U32(req, attribute, val) \ - { \ - u16 attribute_len = 4; \ - __le32 le32val = cpu_to_le32(val);\ - struct sk_buff *req_p = req; \ - fapi_append_data((req_p), (u8 *)&(attribute), 2); \ - fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ - fapi_append_data((req_p), (u8 *)&le32val, 4); \ - } - -#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, val, val_len) \ - { \ - u16 attribute_len = (val_len); \ - struct sk_buff *req_p = req; \ - fapi_append_data((req_p), (u8 *)&(attribute), 2); \ - fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ - fapi_append_data((req_p), (val), (attribute_len)); \ - } - -static u32 slsi_mlme_nan_append_tlv(struct sk_buff *req, u16 tag, u16 len, u8 *data) -{ - u8 *p; - - p = fapi_append_data_u16(req, tag); - p = fapi_append_data_u16(req, len); - p = fapi_append_data(req, data, len); - if (p) - return 0; - return 1; -} - -static u32 slsi_mlme_nan_append_config_tlv(struct sk_buff *req, u8 master_pref, u16 include_ps_id, u8 ps_id_count, - u16 include_ss_id, u8 ss_id_count, u16 rssi_window, u32 nmi_rand_interval, - u16 cluster_merge) -{ - u8 *p; - - p = fapi_append_data_u16(req, SLSI_NAN_TLV_TAG_CONFIGURATION); - p = fapi_append_data_u16(req, 0x000f); - p = fapi_append_data_u8(req, master_pref); - - /* publish service ID inclusion in beacon */ - p = fapi_append_data_bool(req, include_ps_id); - p = fapi_append_data_u8(req, ps_id_count); - - /* subscribe service ID inclusion in beacon */ - p = fapi_append_data_bool(req, include_ss_id); - p = fapi_append_data_u8(req, ss_id_count); - - p = fapi_append_data_u16(req, rssi_window); - p = fapi_append_data_u32(req, nmi_rand_interval); - p = fapi_append_data_u16(req, cluster_merge); - - if (p) - return 0; - return 1; -} - -static u32 slsi_mlme_nan_append_band_specific_config(struct sk_buff *req, u16 tag, u8 rssi_close, u8 rssi_middle, - u8 rssi_proximity, u8 dwell_time, u16 scan_period, - u16 use_dw_int_val, u8 dw_interval) -{ - u8 *p; - - p = fapi_append_data_u16(req, tag); - p = fapi_append_data_u16(req, 0x0009); - p = fapi_append_data_u8(req, rssi_close); - p = fapi_append_data_u8(req, rssi_middle); - p = fapi_append_data_u8(req, rssi_proximity); - p = fapi_append_data_u8(req, dwell_time); - p = fapi_append_data_u16(req, scan_period); - p = fapi_append_data_bool(req, use_dw_int_val); - p = fapi_append_data_u8(req, dw_interval); - if (p) - return 0; - return 1; -} - -static u32 slsi_mlme_nan_append_2g4_band_specific_config(struct sk_buff *req, u8 rssi_close, u8 rssi_middle, - u8 rssi_proximity, u8 dwell_time, u16 scan_period, - u16 use_dw_int_val, u8 dw_interval) -{ - return slsi_mlme_nan_append_band_specific_config(req, SLSI_NAN_TLV_TAG_2G4_BAND_SPECIFIC_CONFIG, rssi_close, - rssi_middle, rssi_proximity, dwell_time, scan_period, - use_dw_int_val, dw_interval); -} - -static u32 slsi_mlme_nan_append_5g_band_specific_config(struct sk_buff *req, u8 rssi_close, u8 rssi_middle, - u8 rssi_proximity, u8 dwell_time, u16 scan_period, - u16 use_dw_int_val, u8 dw_interval) -{ - return slsi_mlme_nan_append_band_specific_config(req, SLSI_NAN_TLV_TAG_5G_BAND_SPECIFIC_CONFIG, rssi_close, - rssi_middle, rssi_proximity, dwell_time, scan_period, - use_dw_int_val, dw_interval); -} - -static u32 slsi_mlme_nan_append_discovery_config(struct sk_buff *req, u8 sd_type, u8 tx_type, u16 ttl, u16 dw_period, - u8 dw_count, u8 disc_match_ind, u16 use_rssi_thres, u16 ranging_req, - u16 data_path_req) -{ - u8 *p; - - p = fapi_append_data_u16(req, SLSI_NAN_TLV_TAG_DISCOVERY_COMMON_SPECIFIC); - p = fapi_append_data_u16(req, 0x000e); - p = fapi_append_data_u8(req, sd_type); - p = fapi_append_data_u8(req, tx_type); - p = fapi_append_data_u16(req, ttl); - p = fapi_append_data_u16(req, dw_period); - p = fapi_append_data_u8(req, dw_count); - p = fapi_append_data_u8(req, disc_match_ind); - p = fapi_append_data_bool(req, use_rssi_thres); - p = fapi_append_data_bool(req, ranging_req); - p = fapi_append_data_bool(req, data_path_req); - if (p) - return 0; - return 1; -} - -static u32 slsi_mlme_nan_append_subscribe_specific(struct sk_buff *req, u8 srf_type, u16 respond_if_in_address_set, - u16 use_srf, u16 ssi_required_for_match) -{ - u8 *p; - - p = fapi_append_data_u16(req, SLSI_NAN_TLV_TAG_SUBSCRIBE_SPECIFIC); - p = fapi_append_data_u16(req, 0x0007); - p = fapi_append_data_u8(req, srf_type); - p = fapi_append_data_u16(req, respond_if_in_address_set); - p = fapi_append_data_u16(req, use_srf); - p = fapi_append_data_u16(req, ssi_required_for_match); - if (p) - return 0; - return 1; -} - -static u32 slsi_mlme_nan_append_address_set(struct sk_buff *req, u16 count, u8 *addresses) -{ - if (!count) - return 0; - return slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_INTERFACE_ADDRESS_SET, count * 6, addresses); -} - -static u32 slsi_mlme_nan_append_service_name(struct sk_buff *req, u16 len, u8 *data) -{ - if (!len) - return 0; - return slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_SERVICE_NAME, len, data); -} - -static u32 slsi_mlme_nan_append_service_specific_info(struct sk_buff *req, u16 len, u8 *data) -{ - if (!len) - return 0; - return slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_SERVICE_SPECIFIC_INFO, len, data); -} - -static u32 slsi_mlme_nan_append_ext_service_specific_info(struct sk_buff *req, u16 len, u8 *data) -{ - if (!len) - return 0; - return slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_EXT_SERVICE_SPECIFIC_INFO, len, data); -} - -static u32 slsi_mlme_nan_append_tx_match_filter(struct sk_buff *req, u16 len, u8 *data) -{ - if (!len) - return 0; - return slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_TX_MATCH_FILTER, len, data); -} - -static u32 slsi_mlme_nan_append_rx_match_filter(struct sk_buff *req, u16 len, u8 *data) -{ - if (!len) - return 0; - return slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_RX_MATCH_FILTER, len, data); -} - -static u32 slsi_mlme_nan_append_data_path_sec(struct sk_buff *req, struct slsi_nan_security_info *sec_info) -{ - u8 *p, *len_p; - u32 pmk = 0; - u8 passphrase_len = 0; - u8 *passphrase; - u8 sec_type = sec_info->key_info.key_type; - - if (sec_info->key_info.key_type == 1) { - pmk = *(u32 *)sec_info->key_info.body.pmk_info.pmk; - } else if (sec_info->key_info.key_type == 2) { - passphrase_len = sec_info->key_info.body.passphrase_info.passphrase_len; - passphrase = sec_info->key_info.body.passphrase_info.passphrase; - } else { - sec_type = 0; - } - - p = fapi_append_data_u16(req, SLSI_NAN_TLV_TAG_DATA_PATH_SECURITY); - p = fapi_append_data_u16(req, 0x0007); - len_p = p; - p = fapi_append_data_u8(req, sec_type); - p = fapi_append_data_u8(req, sec_info->cipher_type); - p = fapi_append_data_u32(req, sec_info->key_info.key_type); - p = fapi_append_data_u8(req, passphrase_len); - if (passphrase_len) - p = fapi_append_data(req, passphrase, passphrase_len); - if (!p) - return 1; - *len_p = 7 + passphrase_len; - return 0; -} - -static u32 slsi_mlme_nan_append_ranging(struct sk_buff *req, struct slsi_nan_ranging_cfg *ranging_cfg) -{ - u8 *p; - - p = fapi_append_data_u16(req, SLSI_NAN_TLV_TAG_RANGING); - p = fapi_append_data_u16(req, 0x0007); - p = fapi_append_data_u32(req, ranging_cfg->ranging_interval_msec); - p = fapi_append_data_u8(req, ranging_cfg->config_ranging_indications); - p = fapi_append_data_u16(req, ranging_cfg->distance_ingress_mm / 10); - p = fapi_append_data_u16(req, ranging_cfg->distance_egress_mm / 10); - if (p) - return 0; - return 1; -} - -static u32 slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_nan_enable_req *hal_req) -{ - u16 publish_id_inc, service_id_inc; - u8 publish_id_inc_count = 0; - u8 service_id_inc_count = 0; - u8 rssi_close, rssi_middle, rssi_proximity; - u16 rssi_window = hal_req->config_rssi_window_size ? hal_req->rssi_window_size_val : 8; - u32 ret; - - /* NAN configuration TLV */ - publish_id_inc = hal_req->config_sid_beacon && (hal_req->sid_beacon_val & 0x01); - if (publish_id_inc) - publish_id_inc_count = hal_req->sid_beacon_val >> 1; - service_id_inc = hal_req->config_subscribe_sid_beacon && (hal_req->subscribe_sid_beacon_val & 0x01); - if (service_id_inc) - service_id_inc_count = hal_req->subscribe_sid_beacon_val >> 1; - ret = slsi_mlme_nan_append_config_tlv(req, hal_req->master_pref, publish_id_inc, publish_id_inc_count, - service_id_inc, service_id_inc_count, rssi_window, - hal_req->disc_mac_addr_rand_interval_sec, 1); - if (ret) { - SLSI_WARN_NODEV("Error append config TLV\n"); - return ret; - } - - /* 2.4G NAN band specific config TLV*/ - rssi_close = hal_req->config_2dot4g_rssi_close ? hal_req->rssi_close_2dot4g_val : 0; - rssi_middle = hal_req->config_2dot4g_rssi_middle ? hal_req->rssi_middle_2dot4g_val : 0; - rssi_proximity = hal_req->config_2dot4g_rssi_proximity ? hal_req->rssi_proximity_2dot4g_val : 0; - ret = slsi_mlme_nan_append_2g4_band_specific_config(req, rssi_close, rssi_middle, rssi_proximity, - hal_req->scan_params_val.dwell_time[0], - hal_req->scan_params_val.scan_period[0], - (u16)hal_req->config_2dot4g_dw_band, - hal_req->dw_2dot4g_interval_val); - if (ret) { - SLSI_WARN_NODEV("Error append 2.4G band specific TLV\n"); - return ret; - } - - /* 5G NAN band specific config TLV*/ - if (hal_req->config_support_5g && hal_req->support_5g_val) { - rssi_close = hal_req->config_5g_rssi_close ? hal_req->rssi_close_5g_val : 0; - rssi_middle = hal_req->config_5g_rssi_middle ? hal_req->rssi_middle_5g_val : 0; - rssi_proximity = hal_req->config_5g_rssi_close_proximity ? hal_req->rssi_close_proximity_5g_val : 0; - ret = slsi_mlme_nan_append_5g_band_specific_config(req, rssi_close, rssi_middle, rssi_proximity, - hal_req->scan_params_val.dwell_time[1], - hal_req->scan_params_val.scan_period[1], - (u16)hal_req->config_5g_dw_band, - hal_req->dw_5g_interval_val); - if (ret) { - SLSI_WARN_NODEV("Error append 5G band specific TLV\n"); - return ret; - } - } - - return ret; -} - -int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_oper_ctrl = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - - /* mbulk data length = 0x0f + 4 + 2 * (9 + 4) = 45*/ - req = fapi_alloc(mlme_nan_start_req, MLME_NAN_START_REQ, ndev_vif->ifnum, 45); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT | - FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT; - - fapi_set_u16(req, u.mlme_nan_start_req.nan_operation_control_flags, nan_oper_ctrl); - - r = slsi_mlme_nan_enable_fapi_data(req, hal_req); - if (r) { - SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_START_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_START_CFM(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -static u32 slsi_mlme_nan_publish_fapi_data(struct sk_buff *req, struct slsi_hal_nan_publish_req *hal_req) -{ - u32 ret; - - ret = slsi_mlme_nan_append_discovery_config(req, hal_req->publish_type, hal_req->tx_type, hal_req->ttl, - hal_req->period, hal_req->publish_count, hal_req->publish_match_indicator, - (u16)hal_req->rssi_threshold_flag, (u16)0, (u16)0); - if (ret) { - SLSI_WARN_NODEV("Error append disovery config TLV\n"); - return ret; - } - - if (hal_req->service_name_len) { - ret = slsi_mlme_nan_append_service_name(req, hal_req->service_name_len, hal_req->service_name); - if (ret) { - SLSI_WARN_NODEV("Error append servicename TLV\n"); - return ret; - } - } - - if (hal_req->service_specific_info_len) { - ret = slsi_mlme_nan_append_service_specific_info(req, hal_req->service_specific_info_len, - hal_req->service_specific_info); - if (ret) { - SLSI_WARN_NODEV("Error append servSpecInfo TLV\n"); - return ret; - } - } - - if (hal_req->sdea_service_specific_info_len) { - ret = slsi_mlme_nan_append_ext_service_specific_info(req, hal_req->sdea_service_specific_info_len, - hal_req->sdea_service_specific_info); - if (ret) { - SLSI_WARN_NODEV("Error append extServSpecInfo TLV\n"); - return ret; - } - } - - if (hal_req->rx_match_filter_len) { - ret = slsi_mlme_nan_append_rx_match_filter(req, hal_req->rx_match_filter_len, hal_req->rx_match_filter); - if (ret) { - SLSI_WARN_NODEV("Error append rx match filter TLV\n"); - return ret; - } - } - - if (hal_req->tx_match_filter_len) { - ret = slsi_mlme_nan_append_tx_match_filter(req, hal_req->tx_match_filter_len, hal_req->tx_match_filter); - if (ret) { - SLSI_WARN_NODEV("Error append tx match filter TLV\n"); - return ret; - } - } - - ret = slsi_mlme_nan_append_data_path_sec(req, &hal_req->sec_info); - if (ret) { - SLSI_WARN_NODEV("Error append datapath sec TLV\n"); - return ret; - } - ret = slsi_mlme_nan_append_ranging(req, &hal_req->ranging_cfg); - if (ret) - SLSI_WARN_NODEV("Error append ranging config TLV\n"); - return ret; -} - -int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_publish_req *hal_req, - u16 publish_id) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_sdf_flags = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - if (hal_req) { - /* discovery_config_tlv, datapath_sec_tlv, ranging_cfg_tlv */ - u16 length = 18 + 70 + 11; - - length += hal_req->service_name_len ? hal_req->service_name_len + 4 : 0; - length += hal_req->service_specific_info_len ? hal_req->service_specific_info_len + 4 : 0; - length += hal_req->rx_match_filter_len ? hal_req->rx_match_filter_len + 4 : 0; - length += hal_req->tx_match_filter_len ? hal_req->tx_match_filter_len + 4 : 0; - length += hal_req->sdea_service_specific_info_len ? hal_req->sdea_service_specific_info_len + 4 : 0; - - req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, length); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - /* Set/Enable corresponding bits to disable any indications - * that follow a publish. - * BIT0 - Disable publish termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - if (hal_req->recv_indication_cfg & BIT(0)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_PUBLISH_END_EVENT; - if (hal_req->recv_indication_cfg & BIT(1)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT; - if (hal_req->recv_indication_cfg & BIT(2)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT; - } else { - req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 0); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - } - - fapi_set_u16(req, u.mlme_nan_publish_req.publish_id, publish_id); - fapi_set_u16(req, u.mlme_nan_publish_req.nan_sdf_flags, nan_sdf_flags); - - if (hal_req) { - r = slsi_mlme_nan_publish_fapi_data(req, hal_req); - if (r) { - SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - } - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_PUBLISH_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_publish_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_PUBLISH_CFM(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - if (hal_req && !r) - ndev_vif->nan.publish_id_map |= (u32)BIT(publish_id); - else - ndev_vif->nan.publish_id_map &= (u32)~BIT(publish_id); - slsi_kfree_skb(cfm); - return r; -} - -static u32 slsi_mlme_nan_subscribe_fapi_data(struct sk_buff *req, struct slsi_hal_nan_subscribe_req *hal_req) -{ - u32 ret; - - ret = slsi_mlme_nan_append_subscribe_specific(req, hal_req->service_response_filter, - hal_req->service_response_include, - hal_req->use_service_response_filter, - hal_req->ssi_required_for_match_indication); - if (ret) { - SLSI_WARN_NODEV("Error append subscribe specific TLV\n"); - return ret; - } - - ret = slsi_mlme_nan_append_discovery_config(req, hal_req->subscribe_type, - hal_req->subscribe_type ? 0 : 1, hal_req->ttl, - hal_req->period, hal_req->subscribe_count, hal_req->subscribe_match_indicator, - hal_req->rssi_threshold_flag, (u16)0, (u16)0); - if (ret) { - SLSI_WARN_NODEV("Error append discovery config TLV\n"); - return ret; - } - - if (hal_req->service_name_len) { - ret = slsi_mlme_nan_append_service_name(req, hal_req->service_name_len, hal_req->service_name); - if (ret) { - SLSI_WARN_NODEV("Error append service name TLV\n"); - return ret; - } - } - - if (hal_req->service_specific_info_len) { - ret = slsi_mlme_nan_append_service_specific_info(req, hal_req->service_specific_info_len, - hal_req->service_specific_info); - if (ret) { - SLSI_WARN_NODEV("Error append servSpecInfo TLV\n"); - return ret; - } - } - - if (hal_req->rx_match_filter_len) { - ret = slsi_mlme_nan_append_rx_match_filter(req, hal_req->rx_match_filter_len, hal_req->rx_match_filter); - if (ret) { - SLSI_WARN_NODEV("Error append rx match filter TLV\n"); - return ret; - } - } - - if (hal_req->tx_match_filter_len) { - ret = slsi_mlme_nan_append_tx_match_filter(req, hal_req->tx_match_filter_len, hal_req->tx_match_filter); - if (ret) { - SLSI_WARN_NODEV("Error append tx match filter TLV\n"); - return ret; - } - } - - if (hal_req->sdea_service_specific_info_len) { - ret = slsi_mlme_nan_append_ext_service_specific_info(req, hal_req->sdea_service_specific_info_len, - hal_req->sdea_service_specific_info); - if (ret) { - SLSI_WARN_NODEV("Error append extServSpecInfo TLV\n"); - return ret; - } - } - - ret = slsi_mlme_nan_append_data_path_sec(req, &hal_req->sec_info); - if (ret) { - SLSI_WARN_NODEV("Error append datapath sec TLV\n"); - return ret; - } - - ret = slsi_mlme_nan_append_ranging(req, &hal_req->ranging_cfg); - if (ret) { - SLSI_WARN_NODEV("Error append ranging config TLV\n"); - return ret; - } - - ret = slsi_mlme_nan_append_address_set(req, hal_req->num_intf_addr_present, (u8 *)hal_req->intf_addr); - if (ret) - SLSI_WARN_NODEV("Error append address set TLV\n"); - return ret; -} - -int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_subscribe_req *hal_req, - u16 subscribe_id) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_sdf_flags = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - if (hal_req) { - /* subscribespecific + discovery + data_path sec + ranging */ - u16 length = 11 + 18 + 70 + 11; - - length += hal_req->service_name_len ? hal_req->service_name_len + 4 : 0; - length += hal_req->service_specific_info_len ? hal_req->service_specific_info_len + 4 : 0; - length += hal_req->rx_match_filter_len ? hal_req->rx_match_filter_len + 4 : 0; - length += hal_req->tx_match_filter_len ? hal_req->tx_match_filter_len + 4 : 0; - length += hal_req->sdea_service_specific_info_len ? hal_req->sdea_service_specific_info_len + 4 : 0; - length += hal_req->num_intf_addr_present ? hal_req->num_intf_addr_present * 6 + 4 : 0; - - req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, length); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - /* Set/Enable corresponding bits to disable - * indications that follow a subscribe. - * BIT0 - Disable subscribe termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - if (hal_req->recv_indication_cfg & BIT(0)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT; - if (hal_req->recv_indication_cfg & BIT(1)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT; - if (hal_req->recv_indication_cfg & BIT(2)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT; - } else { - req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 0); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - } - - fapi_set_u16(req, u.mlme_nan_subscribe_req.subscribe_id, subscribe_id); - fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags); - - if (hal_req) { - r = slsi_mlme_nan_subscribe_fapi_data(req, hal_req); - if (r) { - SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - } - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_SUBSCRIBE_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_subscribe_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_SUBSCRIBE_CFM(res:0x%04x)\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - if (hal_req && !r) - ndev_vif->nan.subscribe_id_map |= (u32)BIT(subscribe_id); - else - ndev_vif->nan.subscribe_id_map &= (u32)~BIT(subscribe_id); - slsi_kfree_skb(cfm); - return r; -} - -static u32 slsi_mlme_nan_followup_fapi_data(struct sk_buff *req, struct slsi_hal_nan_transmit_followup_req *hal_req) -{ - u32 ret; - - ret = slsi_mlme_nan_append_service_specific_info(req, hal_req->service_specific_info_len, - hal_req->service_specific_info); - if (ret) { - SLSI_WARN_NODEV("Error append service specific info TLV\n"); - return ret; - } - - ret = slsi_mlme_nan_append_ext_service_specific_info(req, hal_req->sdea_service_specific_info_len, - hal_req->sdea_service_specific_info); - if (ret) - SLSI_WARN_NODEV("Error append extServSpecInfo TLV\n"); - return ret; -} - -int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_hal_nan_transmit_followup_req *hal_req) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_sdf_flags = 0; - u16 data_len; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - - data_len = hal_req->service_specific_info_len ? (hal_req->service_specific_info_len + 4) : 0; - data_len = hal_req->sdea_service_specific_info_len ? (hal_req->sdea_service_specific_info_len + 4) : 0; - - /* max possible length for publish attributes: 5*255 */ - req = fapi_alloc(mlme_nan_followup_req, MLME_NAN_FOLLOWUP_REQ, ndev_vif->ifnum, 5 * 255); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - fapi_set_u16(req, u.mlme_nan_followup_req.publish_subscribe_id, hal_req->publish_subscribe_id); - fapi_set_u16(req, u.mlme_nan_followup_req.match_id, hal_req->requestor_instance_id); - fapi_set_u16(req, u.mlme_nan_followup_req.nan_sdf_flags, nan_sdf_flags); - - r = slsi_mlme_nan_followup_fapi_data(req, hal_req); - if (r) { - SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -static u32 slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_nan_config_req *hal_req) -{ - u16 rssi_window = hal_req->config_rssi_window_size ? hal_req->rssi_window_size_val : 8; - u32 ret; - u8 rssi_close = 0, rssi_middle = 0, rssi_proximity = 0; - u16 is_sid_in_beacon = hal_req->config_subscribe_sid_beacon && (hal_req->subscribe_sid_beacon_val & 0x01); - u8 sid_count_in_beacon = hal_req->config_subscribe_sid_beacon ? hal_req->subscribe_sid_beacon_val >> 1 : 0; - - ret = slsi_mlme_nan_append_config_tlv(req, hal_req->master_pref, - hal_req->config_sid_beacon && (hal_req->sid_beacon & 0x01), - hal_req->config_sid_beacon ? hal_req->sid_beacon >> 1 : 0, - is_sid_in_beacon, sid_count_in_beacon, rssi_window, - hal_req->disc_mac_addr_rand_interval_sec, 1); - if (ret) { - SLSI_WARN_NODEV("Error append config TLV\n"); - return ret; - } - - /* 2.4G NAN band specific config*/ - rssi_proximity = hal_req->config_rssi_proximity ? hal_req->rssi_proximity : 0; - ret = slsi_mlme_nan_append_2g4_band_specific_config(req, rssi_close, rssi_middle, rssi_proximity, - hal_req->scan_params_val.dwell_time[0], - hal_req->scan_params_val.scan_period[0], - hal_req->config_2dot4g_dw_band, - hal_req->dw_2dot4g_interval_val); - if (ret) { - SLSI_WARN_NODEV("Error append 2.4G band specific TLV\n"); - return ret; - } - - /* 5G NAN band specific config*/ - rssi_proximity = hal_req->config_5g_rssi_close_proximity ? hal_req->rssi_close_proximity_5g_val : 0; - ret = slsi_mlme_nan_append_5g_band_specific_config(req, rssi_close, rssi_middle, rssi_proximity, - hal_req->scan_params_val.dwell_time[1], - hal_req->scan_params_val.scan_period[1], - hal_req->config_5g_dw_band, - hal_req->dw_5g_interval_val); - if (ret) - SLSI_WARN_NODEV("Error append 5G band specific TLV\n"); - return ret; -} - -int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_config_req *hal_req) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_oper_ctrl = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - /* mbulk data length = 0x0f + 4 + 2 * (9 + 4) = 45 */ - req = fapi_alloc(mlme_nan_config_req, MLME_NAN_CONFIG_REQ, ndev_vif->ifnum, 45); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT | - FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT; - fapi_set_u16(req, u.mlme_nan_config_req.nan_operation_control_flags, nan_oper_ctrl); - - r = slsi_mlme_nan_config_fapi_data(req, hal_req); - if (r) { - SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n"); - slsi_kfree_skb(req); - return -EINVAL; - } - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_CONFIG_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} diff --git a/drivers/net/wireless/scsc/netif.c b/drivers/net/wireless/scsc/netif.c deleted file mode 100755 index 343600b4d3cd..000000000000 --- a/drivers/net/wireless/scsc/netif.c +++ /dev/null @@ -1,2107 +0,0 @@ -/* - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "netif.h" -#include "dev.h" -#include "mgt.h" -#include "scsc_wifi_fcq.h" -#include "ioctl.h" -#include "mib.h" -#include "hip4_sampler.h" - -#define IP4_OFFSET_TO_TOS_FIELD 1 -#define IP6_OFFSET_TO_TC_FIELD_0 0 -#define IP6_OFFSET_TO_TC_FIELD_1 1 -#define FIELD_TO_DSCP 2 - -/* DSCP */ -/* (RFC5865) */ -#define DSCP_VA 0x2C -/* (RFC3246) */ -#define DSCP_EF 0x2E -/* (RFC2597) */ -#define DSCP_AF43 0x26 -#define DSCP_AF42 0x24 -#define DSCP_AF41 0x22 -#define DSCP_AF33 0x1E -#define DSCP_AF32 0x1C -#define DSCP_AF31 0x1A -#define DSCP_AF23 0x16 -#define DSCP_AF22 0x14 -#define DSCP_AF21 0x12 -#define DSCP_AF13 0x0E -#define DSCP_AF12 0x0C -#define DSCP_AF11 0x0A -/* (RFC2474) */ -#define CS7 0x38 -#define CS6 0x30 -#define CS5 0x28 -#define CS4 0x20 -#define CS3 0x18 -#define CS2 0x10 -#define CS0 0x00 -/* (RFC3662) */ -#define CS1 0x08 - -#ifndef CONFIG_ARM -static bool tcp_ack_suppression_disable; -module_param(tcp_ack_suppression_disable, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_disable, "Disable TCP ack suppression feature"); - -static bool tcp_ack_suppression_disable_2g; -module_param(tcp_ack_suppression_disable_2g, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_disable_2g, "Disable TCP ack suppression for only 2.4GHz band"); - -static bool tcp_ack_suppression_monitor = true; -module_param(tcp_ack_suppression_monitor, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_monitor, "TCP ack suppression throughput monitor: Y: enable (default), N: disable"); - -static uint tcp_ack_suppression_monitor_interval = 500; -module_param(tcp_ack_suppression_monitor_interval, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_monitor_interval, "Sampling interval (in ms) for throughput monitor"); - -static uint tcp_ack_suppression_timeout = 16; -module_param(tcp_ack_suppression_timeout, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_timeout, "Timeout (in ms) before cached TCP ack is flushed to tx"); - -static uint tcp_ack_suppression_max = 16; -module_param(tcp_ack_suppression_max, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_max, "Maximum number of TCP acks suppressed before latest flushed to tx"); - -static uint tcp_ack_suppression_rate_very_high = 100; -module_param(tcp_ack_suppression_rate_very_high, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_very_high, "Rate (in Mbps) to apply very high degree of suppression"); - -static uint tcp_ack_suppression_rate_very_high_timeout = 4; -module_param(tcp_ack_suppression_rate_very_high_timeout, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_very_high_timeout, "Timeout (in ms) before cached TCP ack is flushed in very high rate"); - -static uint tcp_ack_suppression_rate_very_high_acks = 20; -module_param(tcp_ack_suppression_rate_very_high_acks, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_very_high_acks, "Maximum number of TCP acks suppressed before latest flushed in very high rate"); - -static uint tcp_ack_suppression_rate_high = 20; -module_param(tcp_ack_suppression_rate_high, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_high, "Rate (in Mbps) to apply high degree of suppression"); - -static uint tcp_ack_suppression_rate_high_timeout = 4; -module_param(tcp_ack_suppression_rate_high_timeout, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_high_timeout, "Timeout (in ms) before cached TCP ack is flushed in high rate"); - -static uint tcp_ack_suppression_rate_high_acks = 16; -module_param(tcp_ack_suppression_rate_high_acks, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_high_acks, "Maximum number of TCP acks suppressed before latest flushed in high rate"); - -static uint tcp_ack_suppression_rate_low = 1; -module_param(tcp_ack_suppression_rate_low, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_low, "Rate (in Mbps) to apply low degree of suppression"); - -static uint tcp_ack_suppression_rate_low_timeout = 4; -module_param(tcp_ack_suppression_rate_low_timeout, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_low_timeout, "Timeout (in ms) before cached TCP ack is flushed in low rate"); - -static uint tcp_ack_suppression_rate_low_acks = 10; -module_param(tcp_ack_suppression_rate_low_acks, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rate_low_acks, "Maximum number of TCP acks suppressed before latest flushed in low rate"); - -static uint tcp_ack_suppression_slow_start_acks = 512; -module_param(tcp_ack_suppression_slow_start_acks, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_slow_start_acks, "Maximum number of Acks sent in slow start"); - -static uint tcp_ack_suppression_rcv_window = 128; -module_param(tcp_ack_suppression_rcv_window, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tcp_ack_suppression_rcv_window, "Receive window size (in unit of Kbytes) that triggers Ack suppression"); - -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE -static void slsi_netif_tcp_ack_suppression_timeout(struct timer_list *t); -#else -static void slsi_netif_tcp_ack_suppression_timeout(unsigned long data); -#endif -static int slsi_netif_tcp_ack_suppression_start(struct net_device *dev); -static int slsi_netif_tcp_ack_suppression_stop(struct net_device *dev); -static struct sk_buff *slsi_netif_tcp_ack_suppression_pkt(struct net_device *dev, struct sk_buff *skb); -#endif - -/* Net Device callback operations */ -static int slsi_net_open(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int err; - unsigned char dev_addr_zero_check[ETH_ALEN]; - - if (WARN_ON(ndev_vif->is_available)) - return -EINVAL; - - if (sdev->mlme_blocked) { - SLSI_NET_WARN(dev, "Fail: called when MLME in blocked state\n"); - return -EIO; - } - - slsi_wakelock(&sdev->wlan_wl); - - /* check if request to rf test mode. */ - slsi_check_rf_test_mode(); - - err = slsi_start(sdev); - if (WARN_ON(err)) { - slsi_wakeunlock(&sdev->wlan_wl); - return err; - } - - if (!sdev->netdev_up_count) { - slsi_get_hw_mac_address(sdev, sdev->hw_addr); - /* Assign Addresses */ - SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_WLAN], sdev->hw_addr); - - SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_P2P], sdev->hw_addr); - sdev->netdev_addresses[SLSI_NET_INDEX_P2P][0] |= 0x02; /* Set the local bit */ - - SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN], sdev->hw_addr); - sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][0] |= 0x02; /* Set the local bit */ - sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][4] ^= 0x80; /* EXOR 5th byte with 0x80 */ -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_NAN], sdev->hw_addr); - sdev->netdev_addresses[SLSI_NET_INDEX_NAN][0] |= 0x02; /* Set the local bit */ - sdev->netdev_addresses[SLSI_NET_INDEX_NAN][3] ^= 0x80; /* EXOR 4th byte with 0x80 */ -#endif - sdev->initial_scan = true; - } - - memset(dev_addr_zero_check, 0, ETH_ALEN); - if (!memcmp(dev->dev_addr, dev_addr_zero_check, ETH_ALEN)) { -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (SLSI_IS_VIF_INDEX_MHS(sdev, ndev_vif)) - SLSI_ETHER_COPY(dev->dev_addr, sdev->netdev_addresses[SLSI_NET_INDEX_P2P]); - else - SLSI_ETHER_COPY(dev->dev_addr, sdev->netdev_addresses[ndev_vif->ifnum]); -#else - SLSI_ETHER_COPY(dev->dev_addr, sdev->netdev_addresses[ndev_vif->ifnum]); -#endif - } - SLSI_ETHER_COPY(dev->perm_addr, sdev->netdev_addresses[ndev_vif->ifnum]); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (ndev_vif->iftype == NL80211_IFTYPE_MONITOR) { - err = slsi_start_monitor_mode(sdev, dev); - if (WARN_ON(err)) { - slsi_wakeunlock(&sdev->wlan_wl); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return err; - } - } -#endif - SLSI_NET_INFO(dev, "ifnum:%d r:%d MAC:%pM\n", ndev_vif->ifnum, sdev->recovery_status, dev->dev_addr); - ndev_vif->is_available = true; - sdev->netdev_up_count++; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) - reinit_completion(&ndev_vif->sig_wait.completion); -#else - INIT_COMPLETION(ndev_vif->sig_wait.completion); -#endif -#ifndef CONFIG_ARM - slsi_netif_tcp_ack_suppression_start(dev); -#endif - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - netif_tx_start_all_queues(dev); - slsi_wakeunlock(&sdev->wlan_wl); - - /* The default power mode in host*/ - /* 2511 measn unifiForceActive and 1 means active */ - if (slsi_is_rf_test_mode_enabled()) { - SLSI_NET_INFO(dev, "*#rf# rf test mode set is enabled.\n"); - slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ENABLED, 0); - slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_MODE, 0); - slsi_set_mib_roam(sdev, NULL, 2511, 1); - slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_TPC_MAX_POWER_RSSI_THRESHOLD, 0); - } - - return 0; -} - -static int slsi_net_stop(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - - SLSI_NET_INFO(dev, "ifnum:%d r:%d\n", ndev_vif->ifnum, sdev->recovery_status); - slsi_wakelock(&sdev->wlan_wl); - netif_tx_stop_all_queues(dev); - sdev->initial_scan = false; - - if (!ndev_vif->is_available) { - /* May have been taken out by the Chip going down */ - SLSI_NET_DBG1(dev, SLSI_NETDEV, "Not available\n"); - slsi_wakeunlock(&sdev->wlan_wl); - return 0; - } -#ifndef SLSI_TEST_DEV - if (!slsi_is_rf_test_mode_enabled() && !sdev->recovery_status) { - SLSI_NET_DBG1(dev, SLSI_NETDEV, "To user mode\n"); - slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_TPC_MAX_POWER_RSSI_THRESHOLD, -55); - } -#endif -#ifndef CONFIG_ARM - slsi_netif_tcp_ack_suppression_stop(dev); -#endif - slsi_stop_net_dev(sdev, dev); - -#ifndef SLSI_TEST_DEV - memset(dev->dev_addr, 0, ETH_ALEN); -#endif - - sdev->allow_switch_40_mhz = true; - sdev->allow_switch_80_mhz = true; - sdev->acs_channel_switched = false; - slsi_wakeunlock(&sdev->wlan_wl); - return 0; -} - -/* This is called after the WE handlers */ -static int slsi_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - SLSI_NET_DBG4(dev, SLSI_NETDEV, "IOCTL cmd:0x%.4x\n", cmd); - - if (cmd == SIOCDEVPRIVATE + 2) { /* 0x89f0 + 2 from wpa_supplicant */ - return slsi_ioctl(dev, rq, cmd); - } - - return -EOPNOTSUPP; -} - -static struct net_device_stats *slsi_net_get_stats(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_NET_DBG4(dev, SLSI_NETDEV, "\n"); - return &ndev_vif->stats; -} - -#ifdef CONFIG_SCSC_USE_WMM_TOS -static u16 slsi_get_priority_from_tos(u8 *frame, u16 proto) -{ - if (WARN_ON(!frame)) - return FAPI_PRIORITY_QOS_UP0; - - switch (proto) { - case ETH_P_IP: /* IPv4 */ - return (u16)(((frame[IP4_OFFSET_TO_TOS_FIELD]) & 0xE0) >> 5); - - case ETH_P_IPV6: /* IPv6 */ - return (u16)((*frame & 0x0E) >> 1); - - default: - return FAPI_PRIORITY_QOS_UP0; - } -} - -#else -static u16 slsi_get_priority_from_tos_dscp(u8 *frame, u16 proto) -{ - u8 dscp; - - if (WARN_ON(!frame)) - return FAPI_PRIORITY_QOS_UP0; - - switch (proto) { - case ETH_P_IP: /* IPv4 */ - dscp = frame[IP4_OFFSET_TO_TOS_FIELD] >> FIELD_TO_DSCP; - break; - - case ETH_P_IPV6: /* IPv6 */ - /* Get traffic class */ - dscp = (((frame[IP6_OFFSET_TO_TC_FIELD_0] & 0x0F) << 4) | - ((frame[IP6_OFFSET_TO_TC_FIELD_1] & 0xF0) >> 4)) >> FIELD_TO_DSCP; - break; - - default: - return FAPI_PRIORITY_QOS_UP0; - } -/* DSCP table based in RFC8325 from Android 10 */ -#if (defined(ANDROID_VERSION) && ANDROID_VERSION >= 100000) - switch (dscp) { - case CS7: - return FAPI_PRIORITY_QOS_UP7; - case CS6: - case DSCP_EF: - case DSCP_VA: - return FAPI_PRIORITY_QOS_UP6; - case CS5: - return FAPI_PRIORITY_QOS_UP5; - case DSCP_AF41: - case DSCP_AF42: - case DSCP_AF43: - case CS4: - case DSCP_AF31: - case DSCP_AF32: - case DSCP_AF33: - case CS3: - return FAPI_PRIORITY_QOS_UP4; - case DSCP_AF21: - case DSCP_AF22: - case DSCP_AF23: - return FAPI_PRIORITY_QOS_UP3; - case CS2: - case DSCP_AF11: - case DSCP_AF12: - case DSCP_AF13: - case CS0: - return FAPI_PRIORITY_QOS_UP0; - case CS1: - return FAPI_PRIORITY_QOS_UP1; - default: - return FAPI_PRIORITY_QOS_UP0; - } -#else - switch (dscp) { - case DSCP_EF: - case DSCP_VA: - return FAPI_PRIORITY_QOS_UP6; - case DSCP_AF43: - case DSCP_AF42: - case DSCP_AF41: - return FAPI_PRIORITY_QOS_UP5; - case DSCP_AF33: - case DSCP_AF32: - case DSCP_AF31: - case DSCP_AF23: - case DSCP_AF22: - case DSCP_AF21: - case DSCP_AF13: - case DSCP_AF12: - case DSCP_AF11: - return FAPI_PRIORITY_QOS_UP0; - case CS7: - return FAPI_PRIORITY_QOS_UP7; - case CS6: - return FAPI_PRIORITY_QOS_UP6; - case CS5: - return FAPI_PRIORITY_QOS_UP5; - case CS4: - return FAPI_PRIORITY_QOS_UP4; - case CS3: - return FAPI_PRIORITY_QOS_UP3; - case CS2: - return FAPI_PRIORITY_QOS_UP2; - case CS1: - return FAPI_PRIORITY_QOS_UP1; - case CS0: - return FAPI_PRIORITY_QOS_UP0; - default: - return FAPI_PRIORITY_QOS_UP0; - } -#endif -} - -#endif - -static bool slsi_net_downgrade_ac(struct net_device *dev, struct sk_buff *skb) -{ - SLSI_UNUSED_PARAMETER(dev); - - switch (skb->priority) { - case 6: - case 7: - skb->priority = FAPI_PRIORITY_QOS_UP5; /* VO -> VI */ - return true; - case 4: - case 5: - skb->priority = FAPI_PRIORITY_QOS_UP3; /* VI -> BE */ - return true; - case 0: - case 3: - skb->priority = FAPI_PRIORITY_QOS_UP2; /* BE -> BK */ - return true; - default: - return false; - } -} - -static u8 slsi_net_up_to_ac_mapping(u8 priority) -{ - switch (priority) { - case FAPI_PRIORITY_QOS_UP6: - case FAPI_PRIORITY_QOS_UP7: - return BIT(FAPI_PRIORITY_QOS_UP6) | BIT(FAPI_PRIORITY_QOS_UP7); - case FAPI_PRIORITY_QOS_UP4: - case FAPI_PRIORITY_QOS_UP5: - return BIT(FAPI_PRIORITY_QOS_UP4) | BIT(FAPI_PRIORITY_QOS_UP5); - case FAPI_PRIORITY_QOS_UP0: - case FAPI_PRIORITY_QOS_UP3: - return BIT(FAPI_PRIORITY_QOS_UP0) | BIT(FAPI_PRIORITY_QOS_UP3); - default: - return BIT(FAPI_PRIORITY_QOS_UP1) | BIT(FAPI_PRIORITY_QOS_UP2); - } -} - -enum slsi_traffic_q slsi_frame_priority_to_ac_queue(u16 priority) -{ - switch (priority) { - case FAPI_PRIORITY_QOS_UP0: - case FAPI_PRIORITY_QOS_UP3: - return SLSI_TRAFFIC_Q_BE; - case FAPI_PRIORITY_QOS_UP1: - case FAPI_PRIORITY_QOS_UP2: - return SLSI_TRAFFIC_Q_BK; - case FAPI_PRIORITY_QOS_UP4: - case FAPI_PRIORITY_QOS_UP5: - return SLSI_TRAFFIC_Q_VI; - case FAPI_PRIORITY_QOS_UP6: - case FAPI_PRIORITY_QOS_UP7: - return SLSI_TRAFFIC_Q_VO; - default: - return SLSI_TRAFFIC_Q_BE; - } -} - -int slsi_ac_to_tids(enum slsi_traffic_q ac, int *tids) -{ - switch (ac) { - case SLSI_TRAFFIC_Q_BE: - tids[0] = FAPI_PRIORITY_QOS_UP0; - tids[1] = FAPI_PRIORITY_QOS_UP3; - break; - - case SLSI_TRAFFIC_Q_BK: - tids[0] = FAPI_PRIORITY_QOS_UP1; - tids[1] = FAPI_PRIORITY_QOS_UP2; - break; - - case SLSI_TRAFFIC_Q_VI: - tids[0] = FAPI_PRIORITY_QOS_UP4; - tids[1] = FAPI_PRIORITY_QOS_UP5; - break; - - case SLSI_TRAFFIC_Q_VO: - tids[0] = FAPI_PRIORITY_QOS_UP6; - tids[1] = FAPI_PRIORITY_QOS_UP7; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static void slsi_net_downgrade_pri(struct net_device *dev, struct slsi_peer *peer, - struct sk_buff *skb) -{ - /* in case we are a client downgrade the ac if acm is - * set and tspec is not established - */ - while (unlikely(peer->wmm_acm & BIT(skb->priority)) && - !(peer->tspec_established & slsi_net_up_to_ac_mapping(skb->priority))) { - SLSI_NET_DBG3(dev, SLSI_NETDEV, "Downgrading from UP:%d\n", skb->priority); - if (!slsi_net_downgrade_ac(dev, skb)) - break; - } - SLSI_NET_DBG4(dev, SLSI_NETDEV, "To UP:%d\n", skb->priority); -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) -static u16 slsi_net_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback) -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -static u16 slsi_net_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv) -#else -static u16 slsi_net_select_queue(struct net_device *dev, struct sk_buff *skb) -#endif -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - u16 netif_q = 0; - struct ethhdr *ehdr = (struct ethhdr *)skb->data; - int proto = 0; - struct slsi_peer *peer; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) - (void)accel_priv; -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) - (void)fallback; -#endif - SLSI_NET_DBG4(dev, SLSI_NETDEV, "\n"); - - /* Defensive check for uninitialized mac header */ - if (!skb_mac_header_was_set(skb)) - skb_reset_mac_header(skb); - - if (is_zero_ether_addr(ehdr->h_dest) || is_zero_ether_addr(ehdr->h_source)) { - SLSI_NET_WARN(dev, "invalid Ethernet addresses (dest:%pM,src:%pM)\n", ehdr->h_dest, ehdr->h_source); - SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len); - return SLSI_NETIF_Q_DISCARD; - } - - proto = be16_to_cpu(eth_hdr(skb)->h_proto); - - switch (proto) { - default: - /* SLSI_NETIF_Q_PRIORITY is used only for EAP, ARP and IP frames with DHCP */ - break; - case ETH_P_PAE: - case ETH_P_WAI: - SLSI_NET_DBG3(dev, SLSI_TX, "EAP packet. Priority Queue Selected\n"); - return SLSI_NETIF_Q_PRIORITY; - case ETH_P_ARP: - SLSI_NET_DBG3(dev, SLSI_TX, "ARP frame. Priority Queue Selected\n"); - return SLSI_NETIF_Q_PRIORITY; - case ETH_P_IP: - if (slsi_is_dhcp_packet(skb->data) == SLSI_TX_IS_NOT_DHCP) - break; - SLSI_NET_DBG3(dev, SLSI_TX, "DHCP packet. Priority Queue Selected\n"); - return SLSI_NETIF_Q_PRIORITY; - } - - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) - /* MULTICAST/BROADCAST Queue is only used for AP */ - if (is_multicast_ether_addr(ehdr->h_dest)) { - SLSI_NET_DBG3(dev, SLSI_TX, "Multicast AC queue will be selected\n"); -#ifdef CONFIG_SCSC_USE_WMM_TOS - skb->priority = slsi_get_priority_from_tos(skb->data + ETH_HLEN, proto); -#else - skb->priority = slsi_get_priority_from_tos_dscp(skb->data + ETH_HLEN, proto); -#endif - return slsi_netif_get_multicast_queue(slsi_frame_priority_to_ac_queue(skb->priority)); - } - - slsi_spinlock_lock(&ndev_vif->peer_lock); - peer = slsi_get_peer_from_mac(sdev, dev, ehdr->h_dest); - if (!peer) { - SLSI_NET_DBG1(dev, SLSI_TX, "Discard: Peer %pM NOT found\n", ehdr->h_dest); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return SLSI_NETIF_Q_DISCARD; - } - - if (peer->qos_enabled) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - if (peer->qos_map_set) { /*802.11 QoS for interworking*/ - skb->priority = cfg80211_classify8021d(skb, &peer->qos_map); - } else -#endif - { -#ifdef CONFIG_SCSC_WLAN_PRIORITISE_IMP_FRAMES - if ((proto == ETH_P_IP && slsi_is_dns_packet(skb->data)) || - (proto == ETH_P_IP && slsi_is_mdns_packet(skb->data)) || - (proto == ETH_P_IP && slsi_is_tcp_sync_packet(dev, skb))) { - skb->priority = FAPI_PRIORITY_QOS_UP7; - } else -#endif - { -#ifdef CONFIG_SCSC_USE_WMM_TOS - skb->priority = slsi_get_priority_from_tos(skb->data + ETH_HLEN, proto); -#else - skb->priority = slsi_get_priority_from_tos_dscp(skb->data + ETH_HLEN, proto); -#endif - } - } - } else{ - skb->priority = FAPI_PRIORITY_QOS_UP0; - } - - /* Downgrade the priority if acm bit is set and tspec is not established */ - slsi_net_downgrade_pri(dev, peer, skb); - - netif_q = slsi_netif_get_peer_queue(peer->queueset, slsi_frame_priority_to_ac_queue(skb->priority)); - SLSI_NET_DBG3(dev, SLSI_TX, "prio:%d queue:%u\n", skb->priority, netif_q); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return netif_q; -} - -void slsi_tdls_move_packets(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_peer *sta_peer, struct slsi_peer *tdls_peer, bool connection) -{ - struct netdev_vif *netdev_vif = netdev_priv(dev); - struct sk_buff *skb = NULL; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) - struct sk_buff *skb_to_free = NULL; -#endif - struct ethhdr *ehdr; - struct Qdisc *qd; - u32 num_pkts; - u16 staq; - u16 tdlsq; - u16 netq; - u16 i; - u16 j; - int index; - struct slsi_tcp_ack_s *tcp_ack; - - /* Get the netdev queue number from queueset */ - staq = slsi_netif_get_peer_queue(sta_peer->queueset, 0); - tdlsq = slsi_netif_get_peer_queue(tdls_peer->queueset, 0); - - SLSI_NET_DBG1(dev, SLSI_TDLS, "Connection: %d, sta_qset: %d, tdls_qset: %d, sta_netq: %d, tdls_netq: %d\n", - connection, sta_peer->queueset, tdls_peer->queueset, staq, tdlsq); - - /* Pause the TDLS queues and STA netdev queues */ - slsi_tx_pause_queues(sdev); - - /* walk through frames in TCP Ack suppression queue and change mapping to TDLS queue */ - for (index = 0; index < TCP_ACK_SUPPRESSION_RECORDS_MAX; index++) { - tcp_ack = &netdev_vif->ack_suppression[index]; - if (!tcp_ack && !tcp_ack->state) - continue; - slsi_spinlock_lock(&tcp_ack->lock); - skb_queue_walk(&tcp_ack->list, skb) { - SLSI_NET_DBG2(dev, SLSI_TDLS, "frame in TCP Ack list (peer:%pM)\n", eth_hdr(skb)->h_dest); - /* is it destined to TDLS peer? */ - if (compare_ether_addr(tdls_peer->address, eth_hdr(skb)->h_dest) == 0) { - if (connection) { - /* TDLS setup: change the queue mapping to TDLS queue */ - skb->queue_mapping += (tdls_peer->queueset * SLSI_NETIF_Q_PER_PEER); - } else { - /* TDLS teardown: change the queue to STA queue */ - skb->queue_mapping -= (tdls_peer->queueset * SLSI_NETIF_Q_PER_PEER); - } - } - } - slsi_spinlock_unlock(&tcp_ack->lock); - } - - /** - * For TDLS connection set PEER valid to true. After this ndo_select_queue() will select TDLSQ instead of STAQ - * For TDLS teardown set PEER valid to false. After this ndo_select_queue() will select STAQ instead of TDLSQ - */ - if (connection) - tdls_peer->valid = true; - else - tdls_peer->valid = false; - - /* Move packets from netdev queues */ - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) { - SLSI_NET_DBG2(dev, SLSI_TDLS, "NETQ%d: Before: tdlsq_len = %d, staq_len = %d\n", - i, dev->_tx[tdlsq + i].qdisc->q.qlen, dev->_tx[staq + i].qdisc->q.qlen); - - if (connection) { - /* Check if any packet is already avilable in TDLS queue (most likely from last session) */ - if (dev->_tx[tdlsq + i].qdisc->q.qlen) - SLSI_NET_ERR(dev, "tdls_connection: Packet present in queue %d\n", tdlsq + i); - - qd = dev->_tx[staq + i].qdisc; - /* Get the total number of packets in STAQ */ - num_pkts = qd->q.qlen; - - /* Check all the pkt in STAQ and move the TDLS pkts to TDSLQ */ - for (j = 0; j < num_pkts; j++) { - qd = dev->_tx[staq + i].qdisc; - /* Dequeue the pkt form STAQ. This logic is similar to kernel API dequeue_skb() */ - skb = qd->gso_skb; - if (skb) { - qd->gso_skb = NULL; - qd->q.qlen--; - } else { - skb = qd->dequeue(qd); - } - - if (!skb) { - SLSI_NET_ERR(dev, "tdls_connection: STA NETQ skb is NULL\n"); - break; - } - - /* Change the queue mapping for the TDLS packets */ - netq = skb->queue_mapping; - ehdr = (struct ethhdr *)skb->data; - if (compare_ether_addr(tdls_peer->address, ehdr->h_dest) == 0) { - netq += (tdls_peer->queueset * SLSI_NETIF_Q_PER_PEER); - SLSI_NET_DBG3(dev, SLSI_TDLS, "NETQ%d: Queue mapping changed from %d to %d\n", - i, skb->queue_mapping, netq); - skb_set_queue_mapping(skb, netq); - } - - qd = dev->_tx[netq].qdisc; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) - qd->enqueue(skb, qd, &skb_to_free); -#else - /* If the netdev queue is already full then enqueue() will drop the skb */ - qd->enqueue(skb, qd); -#endif - } - } else { - num_pkts = dev->_tx[tdlsq + i].qdisc->q.qlen; - /* Move the packets from TDLS to STA queue */ - for (j = 0; j < num_pkts; j++) { - /* Dequeue the pkt form TDLS_Q. This logic is similar to kernel API dequeue_skb() */ - qd = dev->_tx[tdlsq + i].qdisc; - skb = qd->gso_skb; - if (skb) { - qd->gso_skb = NULL; - qd->q.qlen--; - } else { - skb = qd->dequeue(qd); - } - - if (!skb) { - SLSI_NET_ERR(dev, "tdls_teardown: TDLS NETQ skb is NULL\n"); - break; - } - - /* Update the queue mapping */ - skb_set_queue_mapping(skb, staq + i); - - /* Enqueue the packet in STA queue */ - qd = dev->_tx[staq + i].qdisc; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) - qd->enqueue(skb, qd, &skb_to_free); -#else - /* If the netdev queue is already full then enqueue() will drop the skb */ - qd->enqueue(skb, qd); -#endif - } - } - SLSI_NET_DBG2(dev, SLSI_TDLS, "NETQ%d: After : tdlsq_len = %d, staq_len = %d\n", - i, dev->_tx[tdlsq + i].qdisc->q.qlen, dev->_tx[staq + i].qdisc->q.qlen); - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) - if (unlikely(skb_to_free)) - kfree_skb_list(skb_to_free); -#endif - - /* Teardown - after teardown there should not be any packet in TDLS queues */ - if (!connection) - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) { - if (dev->_tx[tdlsq + i].qdisc->q.qlen) - SLSI_NET_ERR(dev, "tdls_teardown: Packet present in NET queue %d\n", tdlsq + i); - } - - /* Resume the STA and TDLS netdev queues */ - slsi_tx_unpause_queues(sdev); -} - -/** - * This is the main TX entry point for the driver. - * - * Ownership of the skb is transferred to another function ONLY IF such - * function was able to deal with that skb and ended with a SUCCESS ret code. - * Owner HAS the RESPONSIBILITY to handle the life cycle of the skb. - * - * In the context of this function: - * - ownership is passed DOWN to the LOWER layers HIP-functions when skbs were - * SUCCESSFULLY transmitted, and there they will be FREED. As a consequence - * kernel netstack will receive back NETDEV_TX_OK too. - * - ownership is KEPT HERE by this function when lower layers fails somehow - * to deal with the transmission of the skb. In this case the skb WOULD HAVE - * NOT BEEN FREED by lower layers that instead returns a proper ERRCODE. - * - intermediate lower layer functions (NOT directly involved in failure or - * success) will relay any retcode up to this layer for evaluation. - * - * WHAT HAPPENS THEN, is ERRCODE-dependent, and at the moment: - * - ENOSPC: something related to queueing happened...this should be - * retried....NETDEV_TX_BUSY is returned to NetStack ...packet will be - * requeued by the Kernel NetStack itself, using the proper queue. - * As a consequence SKB is NOT FREED HERE !. - * - ANY OTHER ERR: all other errors are considered at the moment NOT - * recoverable and SO skbs are droppped(FREED) HERE...Kernel will receive - * the proper ERRCODE and stops dealing with the packet considering it - * consumed by lower layer. (same behavior as NETDEV_TX_OK) - * - * BIG NOTE: - * As detailed in Documentation/networking/drivers.txt the above behavior - * of returning NETDEV_TX_BUSY to trigger requeueinng by the Kernel is - * discouraged and should be used ONLY in case of a real HARD error(?); - * the advised solution is to actively STOP the queues before finishing - * the available space and WAKING them up again when more free buffers - * would have arrived. - */ -static netdev_tx_t slsi_net_hw_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_dev *sdev = ndev_vif->sdev; - int r = NETDEV_TX_OK; - struct sk_buff *original_skb = NULL; -#ifdef CONFIG_SCSC_WLAN_DEBUG - int known_users = 0; -#endif - /* Keep the packet length. The packet length will be used to increment - * stats for the netdev if the packet was successfully transmitted. - * The ownership of the SKB is passed to lower layers, so we should - * not refer the SKB after this point - */ - unsigned int packet_len = skb->len; - enum slsi_traffic_q traffic_q = slsi_frame_priority_to_ac_queue(skb->priority); - - slsi_wakelock(&sdev->wlan_wl); - slsi_skb_cb_init(skb); - - /* Check for misaligned (oddly aligned) data. - * The f/w requires 16 bit aligned. - * This is a corner case - for example, the kernel can generate BPDU - * that are oddly aligned. Therefore it is acceptable to copy these - * frames to a 16 bit alignment. - */ - if ((uintptr_t)skb->data & 0x1) { - struct sk_buff *skb2 = NULL; - /* Received a socket buffer aligned on an odd address. - * Re-align by asking for headroom. - */ - skb2 = skb_copy_expand(skb, SLSI_NETIF_SKB_HEADROOM, skb_tailroom(skb), GFP_ATOMIC); - if (skb2 && (!(((uintptr_t)skb2->data) & 0x1))) { - /* We should account for this duplication */ - original_skb = skb; - skb = skb2; - SLSI_NET_DBG3(dev, SLSI_TX, "Oddly aligned skb realigned\n"); - } else { - /* Drop the packet if we can't re-align. */ - SLSI_NET_WARN(dev, "Oddly aligned skb failed realignment, dropping\n"); - if (skb2) { - SLSI_NET_DBG3(dev, SLSI_TX, "skb_copy_expand didn't align for us\n"); - slsi_kfree_skb(skb2); - } else { - SLSI_NET_DBG3(dev, SLSI_TX, "skb_copy_expand failed when trying to align\n"); - } - r = -EFAULT; - goto evaluate; - } - } - slsi_dbg_track_skb(skb, GFP_ATOMIC); - - /* Be defensive about the mac_header - some kernels have a bug where a - * frame can be delivered to the driver with mac_header initialised - * to ~0U and this causes a crash when the pointer is dereferenced to - * access part of the Ethernet header. - */ - if (!skb_mac_header_was_set(skb)) - skb_reset_mac_header(skb); - - SLSI_NET_DBG3(dev, SLSI_TX, "Proto 0x%.4X\n", be16_to_cpu(eth_hdr(skb)->h_proto)); - - if (!ndev_vif->is_available) { - SLSI_NET_WARN(dev, "vif NOT available\n"); - r = -EFAULT; - goto evaluate; - } - if (skb->queue_mapping == SLSI_NETIF_Q_DISCARD) { - SLSI_NET_WARN(dev, "Discard Queue :: Packet Dropped\n"); - r = -EIO; - goto evaluate; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) - known_users = refcount_read(&skb->users); -#else - known_users = atomic_read(&skb->users); -#endif -#endif - -#ifndef CONFIG_ARM - skb = slsi_netif_tcp_ack_suppression_pkt(dev, skb); - if (!skb) { - slsi_wakeunlock(&sdev->wlan_wl); - if (original_skb) - slsi_kfree_skb(original_skb); - return NETDEV_TX_OK; - } -#endif - - /* SKB is owned by slsi_tx_data() ONLY IF ret value is success (0) */ - r = slsi_tx_data(sdev, dev, skb); -evaluate: - if (r == 0) { - /** - * A copy has been passed down and successfully transmitted - * and freed....here we free the original coming from the - * upper network layers....if a copy was passed down. - */ - if (original_skb) - slsi_kfree_skb(original_skb); - /* skb freed by lower layers on success...enjoy */ - - ndev_vif->tx_packets[traffic_q]++; - ndev_vif->stats.tx_packets++; - ndev_vif->stats.tx_bytes += packet_len; - r = NETDEV_TX_OK; - } else { - /** - * Failed to send: - * - if QueueFull/OutOfMBulk (-ENOSPC returned) the skb was - * NOT discarded by lower layers and NETDEV_TX_BUSY should - * be returned to upper layers: this will cause the skb - * (THAT MUST NOT HAVE BEEN FREED BY LOWER LAYERS !) - * to be requeued ... - * NOTE THAT it's the original skb that will be retried - * by upper netstack. - * THIS CONDITION SHOULD NOT BE REACHED...NEVER...see in - * the following. - * - * - with any other -ERR instead return the error: this - * anyway let the kernel think that the SKB has - * been consumed, and we drop the frame and free it. - * - * - a WARN_ON() takes care to ensure the SKB has NOT been - * freed by someone despite this was NOT supposed to happen, - * just before the actual freeing. - * - */ - if (r == -ENOSPC) { - /* SLSI_NET_DBG1(dev, SLSI_TEST, "Packet Requeued...should NOT get here !\n"); */ - ndev_vif->stats.tx_fifo_errors++; - /* Free the local copy if any ... */ - if (original_skb) - slsi_kfree_skb(skb); - r = NETDEV_TX_BUSY; - } else { -#ifdef CONFIG_SCSC_WLAN_DEBUG -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) - WARN_ON(known_users && refcount_read(&skb->users) != known_users); -#else - WARN_ON(known_users && atomic_read(&skb->users) != known_users); -#endif -#endif - if (original_skb) - slsi_kfree_skb(original_skb); - slsi_kfree_skb(skb); - ndev_vif->stats.tx_dropped++; - /* We return the ORIGINAL Error 'r' anyway - * BUT Kernel treats them as TX complete anyway - * and assumes the SKB has been consumed. - */ - /* SLSI_NET_DBG1(dev, SLSI_TEST, "Packet Dropped\n"); */ - } - } - /* SKBs are always considered consumed if the driver - * returns NETDEV_TX_OK. - */ - slsi_wakeunlock(&sdev->wlan_wl); - return r; -} - -static netdev_features_t slsi_net_fix_features(struct net_device *dev, netdev_features_t features) -{ - SLSI_UNUSED_PARAMETER(dev); - -#ifdef CONFIG_SCSC_WLAN_SG - SLSI_NET_DBG1(dev, SLSI_RX, "Scatter-gather and GSO enabled\n"); - features |= NETIF_F_SG; - features |= NETIF_F_GSO; -#endif - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI_GRO - SLSI_NET_DBG1(dev, SLSI_RX, "NAPI Rx GRO enabled\n"); - features |= NETIF_F_GRO; -#else - SLSI_NET_DBG1(dev, SLSI_RX, "NAPI Rx GRO disabled\n"); - features &= ~NETIF_F_GRO; -#endif - return features; -} - -static void slsi_set_multicast_list(struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u8 count, i = 0; - u8 mdns_addr[ETH_ALEN] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFB }; - -#ifdef CONFIG_SCSC_WLAN_BLOCK_IPV6 - u8 mc_addr_prefix[3] = { 0x01, 0x00, 0x5e }; -#else - u8 mdns6_addr[ETH_ALEN] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0xFB }; - const u8 solicited_node_addr[ETH_ALEN] = { 0x33, 0x33, 0xff, 0x00, 0x00, 0x01 }; - u8 ipv6addr_suffix[3]; -#endif - struct netdev_hw_addr *ha; - - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) - return; - - if (!ndev_vif->is_available) { - SLSI_NET_DBG1(dev, SLSI_NETDEV, "vif NOT available\n"); - return; - } - - count = netdev_mc_count(dev); - if (!count) - goto exit; - -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - slsi_spinlock_lock(&ndev_vif->ipv6addr_lock); - memcpy(ipv6addr_suffix, &ndev_vif->ipv6address.s6_addr[13], 3); - slsi_spinlock_unlock(&ndev_vif->ipv6addr_lock); -#endif - - netdev_for_each_mc_addr(ha, dev) { -#ifdef CONFIG_SCSC_WLAN_BLOCK_IPV6 - if ((!memcmp(ha->addr, mdns_addr, ETH_ALEN)) || /*mDns is handled separately*/ - (memcmp(ha->addr, mc_addr_prefix, 3))) { /*only consider IPv4 multicast addresses*/ -#else - if ((!memcmp(ha->addr, mdns_addr, ETH_ALEN)) || - (!memcmp(ha->addr, mdns6_addr, ETH_ALEN)) || /*mDns is handled separately*/ - (!memcmp(ha->addr, solicited_node_addr, 3) && - !memcmp(&ha->addr[3], ipv6addr_suffix, 3))) { /* local multicast addr handled separately*/ -#endif - - SLSI_NET_DBG3(dev, SLSI_NETDEV, "Drop MAC %pM\n", ha->addr); - continue; - } - if (i == SLSI_MC_ADDR_ENTRY_MAX) { - SLSI_NET_WARN(dev, "MAC list has reached max limit (%d), actual count %d\n", SLSI_MC_ADDR_ENTRY_MAX, count); - break; - } - - SLSI_NET_DBG3(dev, SLSI_NETDEV, "idx %d MAC %pM\n", i, ha->addr); - SLSI_ETHER_COPY(ndev_vif->sta.regd_mc_addr[i++], ha->addr); - } - -exit: - ndev_vif->sta.regd_mc_addr_count = i; -} - -static int slsi_set_mac_address(struct net_device *dev, void *addr) -{ - struct sockaddr *sa = (struct sockaddr *)addr; - - SLSI_NET_DBG1(dev, SLSI_NETDEV, "slsi_set_mac_address %pM\n", sa->sa_data); - SLSI_ETHER_COPY(dev->dev_addr, sa->sa_data); - return 0; -} - -static const struct net_device_ops slsi_netdev_ops = { - .ndo_open = slsi_net_open, - .ndo_stop = slsi_net_stop, - .ndo_start_xmit = slsi_net_hw_xmit, - .ndo_do_ioctl = slsi_net_ioctl, - .ndo_get_stats = slsi_net_get_stats, - .ndo_select_queue = slsi_net_select_queue, - .ndo_fix_features = slsi_net_fix_features, - .ndo_set_rx_mode = slsi_set_multicast_list, - .ndo_set_mac_address = slsi_set_mac_address, -}; - -static void slsi_if_setup(struct net_device *dev) -{ - ether_setup(dev); - dev->netdev_ops = &slsi_netdev_ops; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)) - dev->needs_free_netdev = true; -#else - dev->destructor = free_netdev; -#endif -} - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - -#if defined(CONFIG_SOC_EXYNOS9610) || defined(CONFIG_SOC_EXYNOS9630) || defined(CONFIG_SOC_EXYNOS3830) -#define SCSC_NETIF_RPS_CPUS_MASK "fe" -#else -#define SCSC_NETIF_RPS_CPUS_MASK "0" -#endif - -static void slsi_netif_rps_map_clear(struct net_device *dev) -{ - struct rps_map *map; - - map = rcu_dereference_protected(dev->_rx->rps_map, 1); - if (map) { - RCU_INIT_POINTER(dev->_rx->rps_map, NULL); - kfree_rcu(map, rcu); - SLSI_NET_INFO(dev, "clear rps_cpus map\n"); - } -} - -static int slsi_netif_rps_map_set(struct net_device *dev, char *buf, size_t len) -{ - struct rps_map *old_map, *map; - cpumask_var_t mask; - int err, cpu, i; - static DEFINE_SPINLOCK(rps_map_lock); - - if (!alloc_cpumask_var(&mask, GFP_KERNEL)) - return -ENOMEM; - - err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits); - if (err) { - free_cpumask_var(mask); - SLSI_NET_WARN(dev, "CPU bitmap parse failed\n"); - return err; - } - - map = kzalloc(max_t(unsigned int, RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES), GFP_KERNEL); - if (!map) { - free_cpumask_var(mask); - SLSI_NET_WARN(dev, "CPU mask alloc failed\n"); - return -ENOMEM; - } - - i = 0; - for_each_cpu_and(cpu, mask, cpu_online_mask) - map->cpus[i++] = cpu; - - if (i) { - map->len = i; - } else { - kfree(map); - map = NULL; - } - - spin_lock(&rps_map_lock); - old_map = rcu_dereference_protected(dev->_rx->rps_map, lockdep_is_held(&rps_map_lock)); - rcu_assign_pointer(dev->_rx->rps_map, map); - spin_unlock(&rps_map_lock); - - if (map) - static_key_slow_inc(&rps_needed); - if (old_map) - static_key_slow_dec(&rps_needed); - - if (old_map) - kfree_rcu(old_map, rcu); - - free_cpumask_var(mask); - SLSI_NET_INFO(dev, "rps_cpus map set(%s)\n", buf); - return len; -} -#endif - -int slsi_netif_add_locked(struct slsi_dev *sdev, const char *name, int ifnum) -{ - struct net_device *dev = NULL; - struct netdev_vif *ndev_vif; - struct wireless_dev *wdev; - int alloc_size, txq_count = 0, ret; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->netdev_add_remove_mutex)); - - if (WARN_ON(!sdev || ifnum > CONFIG_SCSC_WLAN_MAX_INTERFACES || sdev->netdev[ifnum])) - return -EINVAL; - - alloc_size = sizeof(struct netdev_vif); - - txq_count = SLSI_NETIF_Q_PEER_START + (SLSI_NETIF_Q_PER_PEER * (SLSI_ADHOC_PEER_CONNECTIONS_MAX)); - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 16, 0)) - dev = alloc_netdev_mqs(alloc_size, name, NET_NAME_PREDICTABLE, slsi_if_setup, txq_count, 1); -#else - dev = alloc_netdev_mqs(alloc_size, name, slsi_if_setup, txq_count, 1); -#endif - if (!dev) { - SLSI_ERR(sdev, "Failed to allocate private data for netdev\n"); - return -ENOMEM; - } - - /* Reserve space in skb for later use */ - dev->needed_headroom = SLSI_NETIF_SKB_HEADROOM; - dev->needed_tailroom = SLSI_NETIF_SKB_TAILROOM; - - ret = dev_alloc_name(dev, dev->name); - if (ret < 0) - goto exit_with_error; - - ndev_vif = netdev_priv(dev); - memset(ndev_vif, 0x00, sizeof(*ndev_vif)); - SLSI_MUTEX_INIT(ndev_vif->vif_mutex); - SLSI_MUTEX_INIT(ndev_vif->scan_mutex); - SLSI_MUTEX_INIT(ndev_vif->scan_result_mutex); - skb_queue_head_init(&ndev_vif->ba_complete); - slsi_sig_send_init(&ndev_vif->sig_wait); - ndev_vif->sdev = sdev; - ndev_vif->ifnum = ifnum; - ndev_vif->vif_type = SLSI_VIFTYPE_UNSPECIFIED; -#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - slsi_spinlock_create(&ndev_vif->ipv6addr_lock); -#endif - slsi_spinlock_create(&ndev_vif->peer_lock); - atomic_set(&ndev_vif->ba_flush, 0); - - /* Reserve memory for the peer database - Not required for p2p0/nan interface */ - if (!(SLSI_IS_VIF_INDEX_P2P(ndev_vif) || SLSI_IS_VIF_INDEX_NAN(ndev_vif))) { - int queueset; - - for (queueset = 0; queueset < SLSI_ADHOC_PEER_CONNECTIONS_MAX; queueset++) { - ndev_vif->peer_sta_record[queueset] = kzalloc(sizeof(*ndev_vif->peer_sta_record[queueset]), GFP_KERNEL); - - if (!ndev_vif->peer_sta_record[queueset]) { - int j; - - SLSI_NET_ERR(dev, "Could not allocate memory for peer entry (queueset:%d)\n", queueset); - - /* Free previously allocated peer database memory till current queueset */ - for (j = 0; j < queueset; j++) { - kfree(ndev_vif->peer_sta_record[j]); - ndev_vif->peer_sta_record[j] = NULL; - } - - ret = -ENOMEM; - goto exit_with_error; - } - } - } - - /* The default power mode in host*/ - if (slsi_is_rf_test_mode_enabled()) { - SLSI_NET_ERR(dev, "*#rf# rf test mode set is enabled.\n"); - ndev_vif->set_power_mode = FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE; - } else { - ndev_vif->set_power_mode = FAPI_POWERMANAGEMENTMODE_POWER_SAVE; - } - - INIT_LIST_HEAD(&ndev_vif->sta.network_map); - SLSI_DBG1(sdev, SLSI_NETDEV, "ifnum=%d\n", ndev_vif->ifnum); - - /* For HS2 interface */ - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_NO_VIF; - - /* For p2p0 interface */ - else if (SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - ret = slsi_p2p_init(sdev, ndev_vif); - if (ret) - goto exit_with_error; - } - - INIT_DELAYED_WORK(&ndev_vif->scan_timeout_work, slsi_scan_ind_timeout_handle); - - ret = slsi_skb_work_init(sdev, dev, &ndev_vif->rx_data, "slsi_wlan_rx_data", slsi_rx_netdev_data_work); - if (ret) - goto exit_with_error; - - ret = slsi_skb_work_init(sdev, dev, &ndev_vif->rx_mlme, "slsi_wlan_rx_mlme", slsi_rx_netdev_mlme_work); - if (ret) { - slsi_skb_work_deinit(&ndev_vif->rx_data); - goto exit_with_error; - } - - wdev = &ndev_vif->wdev; - - dev->ieee80211_ptr = wdev; - wdev->wiphy = sdev->wiphy; - wdev->netdev = dev; - wdev->iftype = NL80211_IFTYPE_STATION; - SET_NETDEV_DEV(dev, sdev->dev); - - /* We are not ready to send data yet. */ - netif_carrier_off(dev); - -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (strcmp(name, CONFIG_SCSC_AP_INTERFACE_NAME) == 0) - SLSI_ETHER_COPY(dev->dev_addr, sdev->netdev_addresses[SLSI_NET_INDEX_P2P]); - else - SLSI_ETHER_COPY(dev->dev_addr, sdev->netdev_addresses[ifnum]); -#else - SLSI_ETHER_COPY(dev->dev_addr, sdev->netdev_addresses[ifnum]); -#endif - SLSI_DBG1(sdev, SLSI_NETDEV, "Add:%pM\n", dev->dev_addr); - rcu_assign_pointer(sdev->netdev[ifnum], dev); - ndev_vif->delete_probe_req_ies = false; - ndev_vif->probe_req_ies = NULL; - ndev_vif->probe_req_ie_len = 0; - ndev_vif->drv_in_p2p_procedure = false; - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - slsi_netif_rps_map_set(dev, SCSC_NETIF_RPS_CPUS_MASK, strlen(SCSC_NETIF_RPS_CPUS_MASK)); -#endif - return 0; - -exit_with_error: - mutex_lock(&sdev->netdev_remove_mutex); - free_netdev(dev); - mutex_unlock(&sdev->netdev_remove_mutex); - return ret; -} - -int slsi_netif_dynamic_iface_add(struct slsi_dev *sdev, const char *name) -{ - int index = -EINVAL; - int err; - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - -#if defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000) - if (sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN] == sdev->netdev_ap) { - rcu_assign_pointer(sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN], NULL); - err = slsi_netif_add_locked(sdev, name, SLSI_NET_INDEX_P2PX_SWLAN); - index = err ? err : SLSI_NET_INDEX_P2PX_SWLAN; - } -#else - err = slsi_netif_add_locked(sdev, name, SLSI_NET_INDEX_P2PX_SWLAN); - index = err ? err : SLSI_NET_INDEX_P2PX_SWLAN; -#endif - - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return index; -} - -int slsi_netif_init(struct slsi_dev *sdev) -{ - int i; - - SLSI_DBG3(sdev, SLSI_NETDEV, "\n"); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - - /* Initialize all other netdev interfaces to NULL */ - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) - RCU_INIT_POINTER(sdev->netdev[i], NULL); - - if (slsi_netif_add_locked(sdev, "wlan%d", SLSI_NET_INDEX_WLAN) != 0) { - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -EINVAL; - } - - if (slsi_netif_add_locked(sdev, "p2p%d", SLSI_NET_INDEX_P2P) != 0) { - rtnl_lock(); - slsi_netif_remove_locked(sdev, sdev->netdev[SLSI_NET_INDEX_WLAN]); - rtnl_unlock(); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -EINVAL; - } -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000) - if (slsi_netif_add_locked(sdev, CONFIG_SCSC_AP_INTERFACE_NAME, SLSI_NET_INDEX_P2PX_SWLAN) != 0) { - rtnl_lock(); - slsi_netif_remove_locked(sdev, sdev->netdev[SLSI_NET_INDEX_WLAN]); - slsi_netif_remove_locked(sdev, sdev->netdev[SLSI_NET_INDEX_P2P]); - rtnl_unlock(); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -EINVAL; - } -#endif -#endif -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - if (slsi_netif_add_locked(sdev, "nan%d", SLSI_NET_INDEX_NAN) != 0) { - rtnl_lock(); - slsi_netif_remove_locked(sdev, sdev->netdev[SLSI_NET_INDEX_WLAN]); - slsi_netif_remove_locked(sdev, sdev->netdev[SLSI_NET_INDEX_P2P]); -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -#if defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000) - slsi_netif_remove_locked(sdev, sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]); -#endif -#endif - rtnl_unlock(); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return -EINVAL; - } -#endif - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return 0; -} - -static int slsi_netif_register_locked(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int err; - - WARN_ON(!rtnl_is_locked()); - WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->netdev_add_remove_mutex)); - if (atomic_read(&ndev_vif->is_registered)) { - SLSI_NET_ERR(dev, "Register:%pM Failed: Already registered\n", dev->dev_addr); - return 0; - } - - err = register_netdevice(dev); - if (err) - SLSI_NET_ERR(dev, "Register:%pM Failed\n", dev->dev_addr); - else - atomic_set(&ndev_vif->is_registered, 1); - return err; -} - -int slsi_netif_register_rtlnl_locked(struct slsi_dev *sdev, struct net_device *dev) -{ - int err; - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - err = slsi_netif_register_locked(sdev, dev); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return err; -} - -int slsi_netif_register(struct slsi_dev *sdev, struct net_device *dev) -{ - int err; - - rtnl_lock(); - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - err = slsi_netif_register_locked(sdev, dev); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - rtnl_unlock(); - return err; -} - -void slsi_netif_remove_locked(struct slsi_dev *sdev, struct net_device *dev) -{ - int i; - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_NET_DBG1(dev, SLSI_NETDEV, "Unregister:%pM\n", dev->dev_addr); - - WARN_ON(!rtnl_is_locked()); - WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->netdev_add_remove_mutex)); - - if (atomic_read(&ndev_vif->is_registered)) { - netif_tx_disable(dev); - netif_carrier_off(dev); - - slsi_stop_net_dev(sdev, dev); - } - - rcu_assign_pointer(sdev->netdev[ndev_vif->ifnum], NULL); - synchronize_rcu(); - - /* Free memory of the peer database - Not required for p2p0 interface */ - if (!SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - int queueset; - - for (queueset = 0; queueset < SLSI_ADHOC_PEER_CONNECTIONS_MAX; queueset++) { - kfree(ndev_vif->peer_sta_record[queueset]); - ndev_vif->peer_sta_record[queueset] = NULL; - } - } - - if (SLSI_IS_VIF_INDEX_P2P(ndev_vif)) { - slsi_p2p_deinit(sdev, ndev_vif); - } else if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_NO_VIF; - ndev_vif->vif_type = SLSI_VIFTYPE_UNSPECIFIED; - } - - cancel_delayed_work(&ndev_vif->scan_timeout_work); - ndev_vif->scan[SLSI_SCAN_HW_ID].requeue_timeout_work = false; - - slsi_skb_work_deinit(&ndev_vif->rx_data); - slsi_skb_work_deinit(&ndev_vif->rx_mlme); - - for (i = 0; i < SLSI_SCAN_MAX; i++) - slsi_purge_scan_results(ndev_vif, i); - - slsi_kfree_skb(ndev_vif->sta.mlme_scan_ind_skb); - slsi_roam_channel_cache_prune(dev, 0); - kfree(ndev_vif->probe_req_ies); - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - slsi_netif_rps_map_clear(dev); -#endif - if (atomic_read(&ndev_vif->is_registered)) { - atomic_set(&ndev_vif->is_registered, 0); - unregister_netdevice(dev); - } else { - mutex_lock(&sdev->netdev_remove_mutex); - free_netdev(dev); - mutex_unlock(&sdev->netdev_remove_mutex); - } -} - -void slsi_netif_remove_rtlnl_locked(struct slsi_dev *sdev, struct net_device *dev) -{ - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - slsi_netif_remove_locked(sdev, dev); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); -} - -void slsi_netif_remove(struct slsi_dev *sdev, struct net_device *dev) -{ - rtnl_lock(); - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - slsi_netif_remove_locked(sdev, dev); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - rtnl_unlock(); -} - -void slsi_netif_remove_all(struct slsi_dev *sdev) -{ - int i; - - SLSI_DBG1(sdev, SLSI_NETDEV, "\n"); - rtnl_lock(); - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) - if (sdev->netdev[i]) - slsi_netif_remove_locked(sdev, sdev->netdev[i]); - rcu_assign_pointer(sdev->netdev_ap, NULL); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - rtnl_unlock(); -} - -void slsi_netif_deinit(struct slsi_dev *sdev) -{ - SLSI_DBG1(sdev, SLSI_NETDEV, "\n"); - slsi_netif_remove_all(sdev); -} - -#ifndef CONFIG_ARM -static int slsi_netif_tcp_ack_suppression_start(struct net_device *dev) -{ - int index; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_tcp_ack_s *tcp_ack; - - ndev_vif->last_tcp_ack = NULL; - for (index = 0; index < TCP_ACK_SUPPRESSION_RECORDS_MAX; index++) { - tcp_ack = &ndev_vif->ack_suppression[index]; - tcp_ack->dport = 0; - tcp_ack->daddr = 0; - tcp_ack->sport = 0; - tcp_ack->saddr = 0; - tcp_ack->ack_seq = 0; - tcp_ack->count = 0; - tcp_ack->max = 0; - tcp_ack->age = 0; - skb_queue_head_init(&tcp_ack->list); -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - timer_setup(&tcp_ack->timer, slsi_netif_tcp_ack_suppression_timeout, 0); -#else - tcp_ack->timer.function = slsi_netif_tcp_ack_suppression_timeout; - tcp_ack->timer.data = (unsigned long)tcp_ack; - init_timer(&tcp_ack->timer); -#endif - tcp_ack->state = 1; - slsi_spinlock_create(&tcp_ack->lock); - } - - memset(&ndev_vif->tcp_ack_stats, 0, sizeof(struct slsi_tcp_ack_stats)); - return 0; -} - -static int slsi_netif_tcp_ack_suppression_stop(struct net_device *dev) -{ - int index; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_tcp_ack_s *tcp_ack; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - for (index = 0; index < TCP_ACK_SUPPRESSION_RECORDS_MAX; index++) { - tcp_ack = &ndev_vif->ack_suppression[index]; - del_timer_sync(&tcp_ack->timer); - slsi_spinlock_lock(&tcp_ack->lock); - tcp_ack->state = 0; - skb_queue_purge(&tcp_ack->list); - slsi_spinlock_unlock(&tcp_ack->lock); - } - ndev_vif->last_tcp_ack = NULL; - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return 0; -} - -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE -static void slsi_netif_tcp_ack_suppression_timeout(struct timer_list *t) -#else -static void slsi_netif_tcp_ack_suppression_timeout(unsigned long data) -#endif -{ -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - struct slsi_tcp_ack_s *tcp_ack = from_timer(tcp_ack, t, timer); -#else - struct slsi_tcp_ack_s *tcp_ack = (struct slsi_tcp_ack_s *)data; -#endif - struct sk_buff *skb; - struct netdev_vif *ndev_vif; - struct slsi_dev *sdev; - int r; - - if (!tcp_ack) - return; - - if (!tcp_ack->state) - return; - - slsi_spinlock_lock(&tcp_ack->lock); - while ((skb = skb_dequeue(&tcp_ack->list)) != 0) { - tcp_ack->count = 0; - - if (!skb->dev) { - kfree_skb(skb); - slsi_spinlock_unlock(&tcp_ack->lock); - return; - } - ndev_vif = netdev_priv(skb->dev); - sdev = ndev_vif->sdev; - ndev_vif->tcp_ack_stats.tack_timeout++; - - r = slsi_tx_data(sdev, skb->dev, skb); - if (r == 0) { - ndev_vif->tcp_ack_stats.tack_sent++; - tcp_ack->last_sent = ktime_get(); - } else if (r == -ENOSPC) { - ndev_vif->tcp_ack_stats.tack_dropped++; - slsi_kfree_skb(skb); - } else { - ndev_vif->tcp_ack_stats.tack_dropped++; - } - } - slsi_spinlock_unlock(&tcp_ack->lock); -} - -static int slsi_netif_tcp_ack_suppression_option(struct sk_buff *skb, u32 option) -{ - unsigned char *options; - u32 optlen = 0, len = 0; - - if (tcp_hdr(skb)->doff > 5) - optlen = (tcp_hdr(skb)->doff - 5) * 4; - - options = ((u8 *)tcp_hdr(skb)) + TCP_ACK_SUPPRESSION_OPTIONS_OFFSET; - - while (optlen > 0) { - switch (options[0]) { - case TCP_ACK_SUPPRESSION_OPTION_EOL: - return 0; - case TCP_ACK_SUPPRESSION_OPTION_NOP: - len = 1; - break; - case TCP_ACK_SUPPRESSION_OPTION_MSS: - if (option == TCP_ACK_SUPPRESSION_OPTION_MSS) - return ((options[2] << 8) | options[3]); - len = options[1]; - break; - case TCP_ACK_SUPPRESSION_OPTION_WINDOW: - if (option == TCP_ACK_SUPPRESSION_OPTION_WINDOW) - return options[2]; - len = 1; - break; - case TCP_ACK_SUPPRESSION_OPTION_SACK: - if (option == TCP_ACK_SUPPRESSION_OPTION_SACK) - return 1; - len = options[1]; - break; - default: - len = options[1]; - break; - } - /* if length field in TCP options is 0, or greater than - * total options length, then options are incorrect; return here - */ - if ((len == 0) || (len > optlen)) { - SLSI_DBG_HEX_NODEV(SLSI_TX, skb->data, skb->len < 128 ? skb->len : 128, "SKB:\n"); - return 0; - } - optlen -= len; - options += len; - } - return 0; -} - -static void slsi_netif_tcp_ack_suppression_syn(struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_tcp_ack_s *tcp_ack; - int index; - - SLSI_NET_DBG2(dev, SLSI_TX, "\n"); - for (index = 0; index < TCP_ACK_SUPPRESSION_RECORDS_MAX; index++) { - tcp_ack = &ndev_vif->ack_suppression[index]; - slsi_spinlock_lock(&tcp_ack->lock); - - if (!tcp_ack->state) { - slsi_spinlock_unlock(&tcp_ack->lock); - return; - } - /* Recover old/hung/unused record. */ - if (tcp_ack->daddr) { - if (ktime_to_ms(ktime_sub(ktime_get(), tcp_ack->last_sent)) >= TCP_ACK_SUPPRESSION_RECORD_UNUSED_TIMEOUT * 1000) { - SLSI_NET_DBG2(dev, SLSI_TX, "delete at %d (%pI4.%d > %pI4.%d)\n", index, &tcp_ack->saddr, ntohs(tcp_ack->sport), &tcp_ack->daddr, ntohs(tcp_ack->dport)); - skb_queue_purge(&tcp_ack->list); - tcp_ack->dport = 0; - tcp_ack->sport = 0; - tcp_ack->daddr = 0; - tcp_ack->saddr = 0; - tcp_ack->count = 0; - tcp_ack->ack_seq = 0; - del_timer(&tcp_ack->timer); - } - } - - if (tcp_ack->daddr == 0) { - SLSI_NET_DBG2(dev, SLSI_TX, "add at %d (%pI4.%d > %pI4.%d)\n", index, &ip_hdr(skb)->saddr, ntohs(tcp_hdr(skb)->source), &ip_hdr(skb)->daddr, ntohs(tcp_hdr(skb)->dest)); - tcp_ack->daddr = ip_hdr(skb)->daddr; - tcp_ack->saddr = ip_hdr(skb)->saddr; - tcp_ack->dport = tcp_hdr(skb)->dest; - tcp_ack->sport = tcp_hdr(skb)->source; - tcp_ack->count = 0; - tcp_ack->ack_seq = 0; - tcp_ack->slow_start_count = 0; - tcp_ack->tcp_slow_start = true; - if (tcp_ack_suppression_monitor) { - tcp_ack->max = 0; - tcp_ack->age = 0; - } else { - tcp_ack->max = tcp_ack_suppression_max; - tcp_ack->age = tcp_ack_suppression_timeout; - } - tcp_ack->last_sent = ktime_get(); - - if (tcp_ack_suppression_monitor) { - tcp_ack->last_sample_time = ktime_get(); - tcp_ack->last_ack_seq = 0; - tcp_ack->last_tcp_rate = 0; - tcp_ack->num_bytes = 0; - tcp_ack->hysteresis = 0; - } -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - tcp_ack->stream_id = index; -#endif - /* read and validate the window scaling multiplier */ - tcp_ack->window_multiplier = slsi_netif_tcp_ack_suppression_option(skb, TCP_ACK_SUPPRESSION_OPTION_WINDOW); - if (tcp_ack->window_multiplier > 14) - tcp_ack->window_multiplier = 0; - tcp_ack->mss = slsi_netif_tcp_ack_suppression_option(skb, TCP_ACK_SUPPRESSION_OPTION_MSS); - SLSI_NET_DBG2(dev, SLSI_TX, "options: mss:%u, window:%u\n", tcp_ack->mss, tcp_ack->window_multiplier); - SCSC_HIP4_SAMPLER_TCP_SYN(ndev_vif->sdev->minor_prof, index, tcp_ack->mss); - SCSC_HIP4_SAMPLER_TCP_DATA(ndev_vif->sdev->minor_prof, index, be32_to_cpu(tcp_hdr(skb)->seq)); - slsi_spinlock_unlock(&tcp_ack->lock); - return; - } - slsi_spinlock_unlock(&tcp_ack->lock); - } -} - -static void slsi_netif_tcp_ack_suppression_fin(struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_tcp_ack_s *tcp_ack; - int index; - - SLSI_NET_DBG2(dev, SLSI_TX, "\n"); - for (index = 0; index < TCP_ACK_SUPPRESSION_RECORDS_MAX; index++) { - tcp_ack = &ndev_vif->ack_suppression[index]; - slsi_spinlock_lock(&tcp_ack->lock); - - if ((tcp_ack->dport == tcp_hdr(skb)->dest) && - (tcp_ack->daddr == ip_hdr(skb)->daddr)) { - SLSI_NET_DBG2(dev, SLSI_TX, "delete at %d (%pI4.%d > %pI4.%d)\n", index, &tcp_ack->saddr, ntohs(tcp_ack->sport), &tcp_ack->daddr, ntohs(tcp_ack->dport)); - skb_queue_purge(&tcp_ack->list); - tcp_ack->dport = 0; - tcp_ack->sport = 0; - tcp_ack->daddr = 0; - tcp_ack->saddr = 0; - tcp_ack->count = 0; - tcp_ack->ack_seq = 0; - - if (tcp_ack_suppression_monitor) { - tcp_ack->last_ack_seq = 0; - tcp_ack->last_tcp_rate = 0; - tcp_ack->num_bytes = 0; - tcp_ack->hysteresis = 0; - } - - del_timer(&tcp_ack->timer); -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - tcp_ack->stream_id = 0; -#endif - SCSC_HIP4_SAMPLER_TCP_FIN(ndev_vif->sdev->minor_prof, index); - slsi_spinlock_unlock(&tcp_ack->lock); - return; - } - slsi_spinlock_unlock(&tcp_ack->lock); - } -} - -static struct sk_buff *slsi_netif_tcp_ack_suppression_pkt(struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int index, found; - struct slsi_tcp_ack_s *tcp_ack; - int forward_now = 0, flush = 0; - struct sk_buff *cskb = 0; - u32 tcp_recv_window_size = 0; - - if (tcp_ack_suppression_disable) - return skb; - - if (tcp_ack_suppression_disable_2g && !SLSI_IS_VIF_CHANNEL_5G(ndev_vif)) - return skb; - - /* for AP type (AP or P2P Go) check if the packet is local or intra BSS. If intra BSS then - * the IP header and TCP header are not set; so return the SKB - */ - if ((ndev_vif->vif_type == FAPI_VIFTYPE_AP) && (compare_ether_addr(eth_hdr(skb)->h_source, dev->dev_addr) != 0)) - return skb; - - /* Return SKB that doesn't match. */ - if (be16_to_cpu(eth_hdr(skb)->h_proto) != ETH_P_IP) - return skb; - if (ip_hdr(skb)->protocol != IPPROTO_TCP) - return skb; - if (!skb_transport_header_was_set(skb)) - return skb; - if (tcp_hdr(skb)->syn) { - slsi_netif_tcp_ack_suppression_syn(dev, skb); - return skb; - } - if (tcp_hdr(skb)->fin) { - slsi_netif_tcp_ack_suppression_fin(dev, skb); - return skb; - } - if (!tcp_hdr(skb)->ack) - return skb; - if (tcp_hdr(skb)->rst) - return skb; - if (tcp_hdr(skb)->urg) - return skb; - - ndev_vif->tcp_ack_stats.tack_acks++; - /* If we find a record, leave the spinlock taken until the end of the function. */ - found = 0; - if (ndev_vif->last_tcp_ack) { - tcp_ack = ndev_vif->last_tcp_ack; - slsi_spinlock_lock(&tcp_ack->lock); - if (!tcp_ack->state) { - slsi_spinlock_unlock(&tcp_ack->lock); - ndev_vif->tcp_ack_stats.tack_sent++; - SLSI_ERR_NODEV("last_tcp_ack record not enabled\n"); - return skb; - } - if ((tcp_ack->dport == tcp_hdr(skb)->dest) && - (tcp_ack->sport == tcp_hdr(skb)->source) && - (tcp_ack->daddr == ip_hdr(skb)->daddr)) { - found = 1; - ndev_vif->tcp_ack_stats.tack_lastrecord++; - } else { - slsi_spinlock_unlock(&tcp_ack->lock); - } - } - if (found == 0) { - /* Search for an existing record on this connection. */ - for (index = 0; index < TCP_ACK_SUPPRESSION_RECORDS_MAX; index++) { - tcp_ack = &ndev_vif->ack_suppression[index]; - - slsi_spinlock_lock(&tcp_ack->lock); - - if (!tcp_ack->state) { - slsi_spinlock_unlock(&tcp_ack->lock); - ndev_vif->tcp_ack_stats.tack_sent++; - SLSI_ERR_NODEV("tcp_ack record %d not enabled\n", index); - return skb; - } - if ((tcp_ack->dport == tcp_hdr(skb)->dest) && - (tcp_ack->sport == tcp_hdr(skb)->source) && - (tcp_ack->daddr == ip_hdr(skb)->daddr)) { - found = 1; - ndev_vif->tcp_ack_stats.tack_searchrecord++; - break; - } - slsi_spinlock_unlock(&tcp_ack->lock); - } - if (found == 0) { - /* No record found, so We cannot suppress the ack, return. */ - ndev_vif->tcp_ack_stats.tack_norecord++; - ndev_vif->tcp_ack_stats.tack_sent++; - return skb; - } - ndev_vif->last_tcp_ack = tcp_ack; - } - - /* If it is a DUP Ack, send straight away without flushing the cache. */ - if (be32_to_cpu(tcp_hdr(skb)->ack_seq) < tcp_ack->ack_seq) { - /* check for wrap-around */ - if (((s32)((u32)be32_to_cpu(tcp_hdr(skb)->ack_seq) - (u32)tcp_ack->ack_seq)) < 0) { - ndev_vif->tcp_ack_stats.tack_dacks++; - ndev_vif->tcp_ack_stats.tack_sent++; - slsi_spinlock_unlock(&tcp_ack->lock); - return skb; - } - } - - /* Has data, forward straight away. */ - if (be16_to_cpu(ip_hdr(skb)->tot_len) > ((ip_hdr(skb)->ihl * 4) + (tcp_hdr(skb)->doff * 4))) { - SCSC_HIP4_SAMPLER_TCP_DATA(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, be32_to_cpu(tcp_hdr(skb)->seq)); - SCSC_HIP4_SAMPLER_TCP_CWND(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, (skb->sk) ? tcp_sk(skb->sk)->snd_cwnd : 0); - SCSC_HIP4_SAMPLER_TCP_SEND_BUF(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, sysctl_tcp_wmem[2]); - ndev_vif->tcp_ack_stats.tack_hasdata++; - forward_now = 1; - goto _forward_now; - } - - /* PSH flag set, forward straight away. */ - if (tcp_hdr(skb)->psh) { - ndev_vif->tcp_ack_stats.tack_psh++; - forward_now = 1; - goto _forward_now; - } - - /* The ECE flag is set for Explicit Congestion Notification supporting connections when the ECT flag - * is set in the segment packet. We must forward ECE marked acks immediately for ECN to work. - */ - if (tcp_hdr(skb)->ece) { - ndev_vif->tcp_ack_stats.tack_ece++; - forward_now = 1; - goto _forward_now; - } - - if (tcp_ack_suppression_monitor) { - /* Measure the throughput of TCP stream by monitoring the bytes Acked by each Ack over a - * sampling period. Based on throughput apply different degree of Ack suppression - */ - if (tcp_ack->last_ack_seq) - tcp_ack->num_bytes += ((u32)be32_to_cpu(tcp_hdr(skb)->ack_seq) - tcp_ack->last_ack_seq); - - tcp_ack->last_ack_seq = be32_to_cpu(tcp_hdr(skb)->ack_seq); - if (ktime_to_ms(ktime_sub(ktime_get(), tcp_ack->last_sample_time)) > tcp_ack_suppression_monitor_interval) { - u16 acks_max; - u32 tcp_rate = ((tcp_ack->num_bytes * 8) / (tcp_ack_suppression_monitor_interval * 1000)); - - SLSI_NET_DBG2(dev, SLSI_TX, "hysteresis:%u total_bytes:%llu rate:%u Mbps\n", - tcp_ack->hysteresis, tcp_ack->num_bytes, tcp_rate); - - /* hysterisis - change only if the variation from last value is more than threshold */ - if ((abs(tcp_rate - tcp_ack->last_tcp_rate)) > tcp_ack->hysteresis) { - if (tcp_rate >= tcp_ack_suppression_rate_very_high) { - tcp_ack->max = tcp_ack_suppression_rate_very_high_acks; - tcp_ack->age = tcp_ack_suppression_rate_very_high_timeout; - } else if (tcp_rate >= tcp_ack_suppression_rate_high) { - tcp_ack->max = tcp_ack_suppression_rate_high_acks; - tcp_ack->age = tcp_ack_suppression_rate_high_timeout; - } else if (tcp_rate >= tcp_ack_suppression_rate_low) { - tcp_ack->max = tcp_ack_suppression_rate_low_acks; - tcp_ack->age = tcp_ack_suppression_rate_low_timeout; - } else { - tcp_ack->max = 0; - tcp_ack->age = 0; - } - - /* Should not be suppressing Acks more than 20% of receiver window size - * doing so can lead to increased RTT and low transmission rate at the - * TCP sender - */ - if (tcp_ack->window_multiplier) - tcp_recv_window_size = be16_to_cpu(tcp_hdr(skb)->window) * (2 << tcp_ack->window_multiplier); - else - tcp_recv_window_size = be16_to_cpu(tcp_hdr(skb)->window); - SCSC_HIP4_SAMPLER_TCP_RWND(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, tcp_recv_window_size); - - acks_max = (tcp_recv_window_size / 5) / (2 * tcp_ack->mss); - if (tcp_ack->max > acks_max) - tcp_ack->max = acks_max; - } - tcp_ack->hysteresis = tcp_rate / 5; /* 20% hysteresis */ - tcp_ack->last_tcp_rate = tcp_rate; - tcp_ack->num_bytes = 0; - tcp_ack->last_sample_time = ktime_get(); - } - } - - /* Do not suppress Selective Acks. */ - if (slsi_netif_tcp_ack_suppression_option(skb, TCP_ACK_SUPPRESSION_OPTION_SACK)) { - ndev_vif->tcp_ack_stats.tack_sacks++; - - /* A TCP selective Ack suggests TCP segment loss. The TCP sender - * may reduce congestion window and limit the number of segments - * it sends before waiting for Ack. - * It is ideal to switch off TCP ack suppression for certain time - * (being replicated here by tcp_ack_suppression_slow_start_acks - * count) and send as many Acks as possible to allow the cwnd to - * grow at the TCP sender - */ - tcp_ack->slow_start_count = 0; - tcp_ack->tcp_slow_start = true; - forward_now = 1; - goto _forward_now; - } - - if (be32_to_cpu(tcp_hdr(skb)->ack_seq) == tcp_ack->ack_seq) { - ndev_vif->tcp_ack_stats.tack_dacks++; - forward_now = 1; - goto _forward_now; - } - - /* When the TCP connection is made, wait until a number of Acks - * are sent before applying the suppression rules. It is to - * allow the cwnd to grow at a normal rate at the TCP sender - */ - if (tcp_ack->tcp_slow_start) { - tcp_ack->slow_start_count++; - if (tcp_ack->slow_start_count >= tcp_ack_suppression_slow_start_acks) { - tcp_ack->slow_start_count = 0; - tcp_ack->tcp_slow_start = false; - } - forward_now = 1; - goto _forward_now; - } - - /* do not suppress if so decided by the TCP monitor */ - if (tcp_ack_suppression_monitor && (!tcp_ack->max || !tcp_ack->age)) { - forward_now = 1; - goto _forward_now; - } - - /* do not suppress delayed Acks that acknowledges for more than 2 TCP - * maximum size segments - */ - if (((u32)be32_to_cpu(tcp_hdr(skb)->ack_seq)) - (tcp_ack->ack_seq) > (2 * tcp_ack->mss)) { - ndev_vif->tcp_ack_stats.tack_delay_acks++; - forward_now = 1; - goto _forward_now; - } - - /* Do not suppress unless the receive window is large - * enough. - * With low receive window size the cwnd can't grow much. - * So suppressing Acks has a negative impact on sender - * rate as it increases the Round trip time measured at - * sender - */ - if (!tcp_ack_suppression_monitor) { - if (tcp_ack->window_multiplier) - tcp_recv_window_size = be16_to_cpu(tcp_hdr(skb)->window) * (2 << tcp_ack->window_multiplier); - else - tcp_recv_window_size = be16_to_cpu(tcp_hdr(skb)->window); - if (tcp_recv_window_size < tcp_ack_suppression_rcv_window * 1024) { - ndev_vif->tcp_ack_stats.tack_low_window++; - forward_now = 1; - goto _forward_now; - } - } - - if (!tcp_ack_suppression_monitor && ktime_to_ms(ktime_sub(ktime_get(), tcp_ack->last_sent)) >= tcp_ack->age) { - ndev_vif->tcp_ack_stats.tack_ktime++; - forward_now = 1; - goto _forward_now; - } - - /* Test for a new cache */ - if (!skb_queue_len(&tcp_ack->list)) { - skb_queue_tail(&tcp_ack->list, skb); - tcp_ack->count = 1; - tcp_ack->ack_seq = be32_to_cpu(tcp_hdr(skb)->ack_seq); - if (tcp_ack->age) - mod_timer(&tcp_ack->timer, jiffies + msecs_to_jiffies(tcp_ack->age)); - slsi_spinlock_unlock(&tcp_ack->lock); - return 0; - } -_forward_now: - cskb = skb_dequeue(&tcp_ack->list); - if (cskb) { - if (tcp_ack_suppression_monitor && tcp_ack->age) - mod_timer(&tcp_ack->timer, jiffies + msecs_to_jiffies(tcp_ack->age)); - ndev_vif->tcp_ack_stats.tack_suppressed++; - slsi_kfree_skb(cskb); - } - skb_queue_tail(&tcp_ack->list, skb); - tcp_ack->ack_seq = be32_to_cpu(tcp_hdr(skb)->ack_seq); - tcp_ack->count++; - if (forward_now) { - flush = 1; - } else { - if (tcp_ack->count >= tcp_ack->max) { - flush = 1; - ndev_vif->tcp_ack_stats.tack_max++; - } - } - if (!flush) { - slsi_spinlock_unlock(&tcp_ack->lock); - return 0; - } - /* Flush the cache. */ - cskb = skb_dequeue(&tcp_ack->list); - tcp_ack->count = 0; - - if (tcp_ack->age) - del_timer(&tcp_ack->timer); - - tcp_ack->last_sent = ktime_get(); - - slsi_spinlock_unlock(&tcp_ack->lock); - ndev_vif->tcp_ack_stats.tack_sent++; - return cskb; -} -#endif diff --git a/drivers/net/wireless/scsc/netif.h b/drivers/net/wireless/scsc/netif.h deleted file mode 100755 index 3a59c9458173..000000000000 --- a/drivers/net/wireless/scsc/netif.h +++ /dev/null @@ -1,105 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "dev.h" - -#ifndef __SLSI_NETIF_H__ -#define __SLSI_NETIF_H__ - -/* net_device queues - * --------------------------------------------- - * 1 Queue for Security frames (EAPOL, WAPI etc) - * 1 Queue for Broadcast/Multicast when in AP mode. - * 4 Queues per Peer - * - * STA/ADHOC - * Queues - * ------------------------------------------------------- - * | 0 | 1 | 2 - 5 | 6 | 7 | 8 | 9 | - * ------------------------------------------------------- - * | Eapol | Discard | Not | AC | AC | AC | AC | - * | Frames | Queue | Used | 0 | 1 | 2 | 3 | - * ------------------------------------------------------- - * - * AP - * Queues - * -------------------------------------------------------- - * | Peer 1 ACs (0 - 4) | Peer 2 ACs (0 - 4) | ...... - * -------------------------------------------------------------------------------------------------------------------- - * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ...... - * -------------------------------------------------------------------------------------------------------------------- - * | Eapol | Discard |B/M Cast |B/M Cast |B/M Cast |B/M Cast | AC | AC | AC | AC | AC | AC | AC | AC | ...... - * | Frames | Queue | AC 0 | AC 1 | AC 2 | AC 3 | 0 | 1 | 2 | 3 | 0 | 1 | 2 | 3 | ...... - * -------------------------------------------------------------------------------------------------------------------- - */ - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888e -#endif -#ifndef ETH_P_WAI -#define ETH_P_WAI 0x88b4 -#endif - -#define SLSI_NETIF_Q_PRIORITY 0 -#define SLSI_NETIF_Q_DISCARD 1 -#define SLSI_NETIF_Q_MULTICAST_START 2 -#define SLSI_NETIF_Q_PEER_START 6 - -#define SLSI_NETIF_Q_PER_PEER 4 - -#define SLSI_NETIF_SKB_HEADROOM (68 + 160) /* sizeof ma_unitdata_req [36] + pad [30] + pad_words [2] */ -#define SLSI_NETIF_SKB_TAILROOM 0 - -#define SLSI_IS_MULTICAST_QUEUE_MAPPING(queue) (queue >= SLSI_NETIF_Q_MULTICAST_START && queue < (SLSI_NETIF_Q_MULTICAST_START + SLSI_NETIF_Q_PER_PEER) ? 1 : 0) - -static inline u16 slsi_netif_get_peer_queue(s16 queueset, s16 ac) -{ - WARN_ON(ac > SLSI_NETIF_Q_PER_PEER); - return SLSI_NETIF_Q_PEER_START + (queueset * SLSI_NETIF_Q_PER_PEER) + ac; -} - -/* queueset is one less than the assigned aid. */ -static inline unsigned short slsi_netif_get_qs_from_queue(short queue, short ac) -{ - return ((queue - ac - SLSI_NETIF_Q_PEER_START) / SLSI_NETIF_Q_PER_PEER); -} - -static inline u16 slsi_netif_get_multicast_queue(s16 ac) -{ - WARN_ON(ac > SLSI_NETIF_Q_PER_PEER); - return SLSI_NETIF_Q_MULTICAST_START + ac; -} - -#define MAP_QS_TO_AID(qs) (qs + 1) -#define MAP_AID_TO_QS(aid) (aid - 1) - -enum slsi_traffic_q { - SLSI_TRAFFIC_Q_BE = 0, - SLSI_TRAFFIC_Q_BK, - SLSI_TRAFFIC_Q_VI, - SLSI_TRAFFIC_Q_VO, -}; - -enum slsi_traffic_q slsi_frame_priority_to_ac_queue(u16 priority); -int slsi_ac_to_tids(enum slsi_traffic_q ac, int *tids); - -struct slsi_dev; -struct slsi_peer; - -int slsi_netif_init(struct slsi_dev *sdev); -/* returns the index or -E code */ -int slsi_netif_dynamic_iface_add(struct slsi_dev *sdev, const char *name); -int slsi_netif_register(struct slsi_dev *sdev, struct net_device *dev); -int slsi_netif_register_rtlnl_locked(struct slsi_dev *sdev, struct net_device *dev); -void slsi_netif_remove(struct slsi_dev *sdev, struct net_device *dev); -void slsi_netif_remove_rtlnl_locked(struct slsi_dev *sdev, struct net_device *dev); -void slsi_netif_remove_all(struct slsi_dev *sdev); -void slsi_netif_deinit(struct slsi_dev *sdev); -void slsi_tdls_move_packets(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_peer *sta_peer, struct slsi_peer *tdls_peer, bool connection); -void slsi_netif_remove_locked(struct slsi_dev *sdev, struct net_device *dev); - -#endif /*__SLSI_NETIF_H__*/ diff --git a/drivers/net/wireless/scsc/nl80211_vendor.c b/drivers/net/wireless/scsc/nl80211_vendor.c deleted file mode 100755 index 7e6c7ac96313..000000000000 --- a/drivers/net/wireless/scsc/nl80211_vendor.c +++ /dev/null @@ -1,5015 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include -#include -#include -#include "dev.h" -#include "cfg80211_ops.h" -#include "debug.h" -#include "mgt.h" -#include "mlme.h" -#include "netif.h" -#include "unifiio.h" -#include "mib.h" -#include "nl80211_vendor.h" - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING -#include "scsc_wifilogger.h" -#include "scsc_wifilogger_rings.h" -#include "scsc_wifilogger_types.h" -#endif -#define SLSI_WIFI_TAG_RSSI 21 -#define SLSI_WIFI_TAG_REASON_CODE 14 -#define SLSI_WIFI_TAG_VENDOR_SPECIFIC 0 -#define SLSI_WIFI_TAG_EAPOL_MESSAGE_TYPE 29 -#define SLSI_WIFI_TAG_STATUS 4 - -#define SLSI_GSCAN_INVALID_RSSI 0x7FFF -#define SLSI_EPNO_AUTH_FIELD_WEP_OPEN 1 -#define SLSI_EPNO_AUTH_FIELD_WPA_PSK 2 -#define SLSI_EPNO_AUTH_FIELD_WPA_EAP 4 -#define WIFI_EVENT_FW_BTM_FRAME_REQUEST 56 // Request for a BTM frame is received -#define WIFI_EVENT_FW_BTM_FRAME_RESPONSE 57 // A BTM frame is transmitted. -#define WIFI_EVENT_FW_NR_FRAME_REQUEST 58 -#define WIFI_EVENT_FW_RM_FRAME_RESPONSE 59 - -#define SLSI_WIFI_TAG_VD_CHANNEL_UTILISATION 0xf01a -#define SLSI_WIFI_TAG_VD_ROAMING_REASON 0xf019 -#define SLSI_WIFI_TAG_VD_BTM_REQUEST_MODE 0xf01b -#define SLSI_WIFI_TAG_VD_BTM_RESPONSE_STATUS 0xf01c -#define SLSI_WIFI_TAG_VD_RETRY_COUNT 0xf00f -#define SLSI_WIFI_TAG_VD_EAPOL_KEY_TYPE 0xF008 -#define SLSI_WIFI_EAPOL_KEY_TYPE_GTK 0x0000 -#define SLSI_WIFI_EAPOL_KEY_TYPE_PTK 0x0001 -#define SLSI_WIFI_ROAMING_SEARCH_REASON_RESERVED 0 -#define SLSI_WIFI_ROAMING_SEARCH_REASON_LOW_RSSI 1 -#define SLSI_WIFI_ROAMING_SEARCH_REASON_LINK_LOSS 2 -#define SLSI_WIFI_ROAMING_SEARCH_REASON_BTM_REQ 3 -#define SLSI_WIFI_ROAMING_SEARCH_REASON_CU_TRIGGER 4 - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING -static int mem_dump_buffer_size; -static char *mem_dump_buffer; -#endif -#ifdef CONFIG_SCSC_WLAN_DEBUG -char *slsi_print_event_name(int event_id) -{ - switch (event_id) { - case SLSI_NL80211_SCAN_RESULTS_AVAILABLE_EVENT: - return "SCAN_RESULTS_AVAILABLE_EVENT"; - case SLSI_NL80211_FULL_SCAN_RESULT_EVENT: - return "FULL_SCAN_RESULT_EVENT"; - case SLSI_NL80211_SCAN_EVENT: - return "BUCKET_SCAN_DONE_EVENT"; -#ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD - case SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH: - return "KEY_MGMT_ROAM_AUTH"; -#endif - case SLSI_NL80211_VENDOR_HANGED_EVENT: - return "SLSI_NL80211_VENDOR_HANGED_EVENT"; - case SLSI_NL80211_EPNO_EVENT: - return "SLSI_NL80211_EPNO_EVENT"; - case SLSI_NL80211_HOTSPOT_MATCH: - return "SLSI_NL80211_HOTSPOT_MATCH"; - case SLSI_NL80211_RSSI_REPORT_EVENT: - return "SLSI_NL80211_RSSI_REPORT_EVENT"; -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING - case SLSI_NL80211_LOGGER_RING_EVENT: - return "SLSI_NL80211_LOGGER_RING_EVENT"; - case SLSI_NL80211_LOGGER_FW_DUMP_EVENT: - return "SLSI_NL80211_LOGGER_FW_DUMP_EVENT"; -#endif - case SLSI_NL80211_NAN_RESPONSE_EVENT: - return "SLSI_NL80211_NAN_RESPONSE_EVENT"; - case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT: - return "SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT"; - case SLSI_NL80211_NAN_MATCH_EVENT: - return "SLSI_NL80211_NAN_MATCH_EVENT"; - case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT: - return "SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT"; - case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT: - return "SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT"; - case SLSI_NL80211_NAN_FOLLOWUP_EVENT: - return "SLSI_NL80211_NAN_FOLLOWUP_EVENT"; - case SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT: - return "SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT"; - case SLSI_NL80211_RTT_RESULT_EVENT: - return "SLSI_NL80211_RTT_RESULT_EVENT"; - case SLSI_NL80211_RTT_COMPLETE_EVENT: - return "SLSI_NL80211_RTT_COMPLETE_EVENT"; - case SLSI_NL80211_VENDOR_ACS_EVENT: - return "SLSI_NL80211_VENDOR_ACS_EVENT"; - case SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS: - return "SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS"; - default: - return "UNKNOWN_EVENT"; - } -} -#endif - -int slsi_vendor_event(struct slsi_dev *sdev, int event_id, const void *data, int len) -{ - struct sk_buff *skb; - -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_MLME, "Event: %s(%d), data = %p, len = %d\n", - slsi_print_event_name(event_id), event_id, data, len); -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, len, event_id, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, len, event_id, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for vendor event: %d\n", event_id); - return -ENOMEM; - } - - nla_put_nohdr(skb, len, data); - - cfg80211_vendor_event(skb, GFP_KERNEL); - - return 0; -} - -static int slsi_vendor_cmd_reply(struct wiphy *wiphy, const void *data, int len) -{ - struct sk_buff *skb; - - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb\n"); - return -ENOMEM; - } - - nla_put_nohdr(skb, len, data); - - return cfg80211_vendor_cmd_reply(skb); -} - -static struct net_device *slsi_gscan_get_netdev(struct slsi_dev *sdev) -{ - return slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); -} - -static struct netdev_vif *slsi_gscan_get_vif(struct slsi_dev *sdev) -{ - struct net_device *dev; - - dev = slsi_gscan_get_netdev(sdev); - if (!dev) { - SLSI_WARN_NODEV("Dev is NULL\n"); - return NULL; - } - - return netdev_priv(dev); -} - -#ifdef CONFIG_SCSC_WLAN_DEBUG -static void slsi_gscan_add_dump_params(struct slsi_nl_gscan_param *nl_gscan_param) -{ - int i; - int j; - - SLSI_DBG2_NODEV(SLSI_GSCAN, "Parameters for SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN sub-command:\n"); - SLSI_DBG2_NODEV(SLSI_GSCAN, "base_period: %d max_ap_per_scan: %d report_threshold_percent: %d report_threshold_num_scans = %d num_buckets: %d\n", - nl_gscan_param->base_period, nl_gscan_param->max_ap_per_scan, - nl_gscan_param->report_threshold_percent, nl_gscan_param->report_threshold_num_scans, - nl_gscan_param->num_buckets); - - for (i = 0; i < nl_gscan_param->num_buckets; i++) { - SLSI_DBG2_NODEV(SLSI_GSCAN, "Bucket: %d\n", i); - SLSI_DBG2_NODEV(SLSI_GSCAN, "\tbucket_index: %d band: %d period: %d report_events: %d num_channels: %d\n", - nl_gscan_param->nl_bucket[i].bucket_index, nl_gscan_param->nl_bucket[i].band, - nl_gscan_param->nl_bucket[i].period, nl_gscan_param->nl_bucket[i].report_events, - nl_gscan_param->nl_bucket[i].num_channels); - - for (j = 0; j < nl_gscan_param->nl_bucket[i].num_channels; j++) - SLSI_DBG2_NODEV(SLSI_GSCAN, "\tchannel_list[%d]: %d\n", - j, nl_gscan_param->nl_bucket[i].channels[j].channel); - } -} - -void slsi_gscan_scan_res_dump(struct slsi_gscan_result *scan_data) -{ - struct slsi_nl_scan_result_param *nl_scan_res = &scan_data->nl_scan_res; - - SLSI_DBG3_NODEV(SLSI_GSCAN, "TS:%llu SSID:%s BSSID:%pM Chan:%d RSSI:%d Bcn_Int:%d Capab:%#x IE_Len:%d\n", - nl_scan_res->ts, nl_scan_res->ssid, nl_scan_res->bssid, nl_scan_res->channel, - nl_scan_res->rssi, nl_scan_res->beacon_period, nl_scan_res->capability, nl_scan_res->ie_length); - - SLSI_DBG_HEX_NODEV(SLSI_GSCAN, &nl_scan_res->ie_data[0], nl_scan_res->ie_length, "IE_Data:\n"); - if (scan_data->anqp_length) { - SLSI_DBG3_NODEV(SLSI_GSCAN, "ANQP_LENGTH:%d\n", scan_data->anqp_length); - SLSI_DBG_HEX_NODEV(SLSI_GSCAN, nl_scan_res->ie_data + nl_scan_res->ie_length, scan_data->anqp_length, "ANQP_info:\n"); - } -} -#endif - -static int slsi_gscan_get_capabilities(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_nl_gscan_capabilities nl_cap; - int ret = 0; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_GET_GSCAN_CAPABILITIES\n"); - - memset(&nl_cap, 0, sizeof(struct slsi_nl_gscan_capabilities)); - - ret = slsi_mib_get_gscan_cap(sdev, &nl_cap); - if (ret != 0) { - SLSI_ERR(sdev, "Failed to read mib\n"); - return ret; - } - - nl_cap.max_scan_cache_size = SLSI_GSCAN_MAX_SCAN_CACHE_SIZE; - nl_cap.max_ap_cache_per_scan = SLSI_GSCAN_MAX_AP_CACHE_PER_SCAN; - nl_cap.max_scan_reporting_threshold = SLSI_GSCAN_MAX_SCAN_REPORTING_THRESHOLD; - - ret = slsi_vendor_cmd_reply(wiphy, &nl_cap, sizeof(struct slsi_nl_gscan_capabilities)); - if (ret) - SLSI_ERR_NODEV("gscan_get_capabilities vendor cmd reply failed (err = %d)\n", ret); - - return ret; -} - -static u32 slsi_gscan_put_channels(struct ieee80211_supported_band *chan_data, bool no_dfs, bool only_dfs, u32 *buf) -{ - u32 chan_count = 0; - u32 chan_flags; - int i; - - if (chan_data == NULL) { - SLSI_DBG3_NODEV(SLSI_GSCAN, "Band not supported\n"); - return 0; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) - chan_flags = (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_OFDM | IEEE80211_CHAN_RADAR); -#else - chan_flags = (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_OFDM | IEEE80211_CHAN_RADAR); -#endif - - for (i = 0; i < chan_data->n_channels; i++) { - if (chan_data->channels[i].flags & IEEE80211_CHAN_DISABLED) - continue; - if (only_dfs) { - if (chan_data->channels[i].flags & chan_flags) - buf[chan_count++] = chan_data->channels[i].center_freq; - continue; - } - if (no_dfs && (chan_data->channels[i].flags & chan_flags)) - continue; - buf[chan_count++] = chan_data->channels[i].center_freq; - } - return chan_count; -} - -static int slsi_gscan_get_valid_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - int ret = 0, type, band; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - u32 *chan_list; - u32 chan_count = 0, mem_len = 0; - struct sk_buff *reply; - - if (len < SLSI_NL_VENDOR_DATA_OVERHEAD) - return -EINVAL; - - type = nla_type(data); - - if (type == GSCAN_ATTRIBUTE_BAND) { - if (nla_len((struct nlattr *)data) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - band = nla_get_u32(data); - } - else - return -EINVAL; - - if (band == 0) { - SLSI_WARN(sdev, "NO Bands. return 0 channel\n"); - return ret; - } - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - SLSI_DBG3(sdev, SLSI_GSCAN, "band %d\n", band); - if (wiphy->bands[NL80211_BAND_2GHZ]) - mem_len += wiphy->bands[NL80211_BAND_2GHZ]->n_channels * sizeof(u32); - - if (wiphy->bands[NL80211_BAND_5GHZ]) - mem_len += wiphy->bands[NL80211_BAND_5GHZ]->n_channels * sizeof(u32); - - if (mem_len == 0) { - ret = -ENOTSUPP; - goto exit; - } - - chan_list = kmalloc(mem_len, GFP_KERNEL); - if (chan_list == NULL) { - ret = -ENOMEM; - goto exit; - } - mem_len += SLSI_NL_VENDOR_REPLY_OVERHEAD + (SLSI_NL_ATTRIBUTE_U32_LEN * 2); - reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_len); - if (reply == NULL) { - ret = -ENOMEM; - goto exit_with_chan_list; - } - switch (band) { - case WIFI_BAND_BG: - chan_count = slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_2GHZ], false, false, chan_list); - break; - case WIFI_BAND_A: - chan_count = slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_5GHZ], true, false, chan_list); - break; - case WIFI_BAND_A_DFS: - chan_count = slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_5GHZ], false, true, chan_list); - break; - case WIFI_BAND_A_WITH_DFS: - chan_count = slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_5GHZ], false, false, chan_list); - break; - case WIFI_BAND_ABG: - chan_count = slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_2GHZ], true, false, chan_list); - chan_count += slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_5GHZ], true, false, chan_list + chan_count); - break; - case WIFI_BAND_ABG_WITH_DFS: - chan_count = slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_2GHZ], false, false, chan_list); - chan_count += slsi_gscan_put_channels(wiphy->bands[NL80211_BAND_5GHZ], false, false, chan_list + chan_count); - break; - default: - chan_count = 0; - SLSI_WARN(sdev, "Invalid Band %d\n", band); - } - nla_put_u32(reply, GSCAN_ATTRIBUTE_NUM_CHANNELS, chan_count); - nla_put(reply, GSCAN_ATTRIBUTE_CHANNEL_LIST, chan_count * sizeof(u32), chan_list); - - ret = cfg80211_vendor_cmd_reply(reply); - - if (ret) - SLSI_ERR(sdev, "FAILED to reply GET_VALID_CHANNELS\n"); - -exit_with_chan_list: - kfree(chan_list); -exit: - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return ret; -} - -struct slsi_gscan_result *slsi_prepare_scan_result(struct sk_buff *skb, u16 anqp_length, int hs2_id) -{ - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - struct slsi_gscan_result *scan_res; - struct timespec ts; - const u8 *ssid_ie; - int mem_reqd; - int ie_len; - u8 *ie; - - ie = &mgmt->u.beacon.variable[0]; - ie_len = fapi_get_datalen(skb) - (ie - (u8 *)mgmt) - anqp_length; - - /* Exclude 1 byte for ie_data[1]. sizeof(u16) to include anqp_length, sizeof(int) for hs_id */ - mem_reqd = (sizeof(struct slsi_gscan_result) - 1) + ie_len + anqp_length + sizeof(int) + sizeof(u16); - - /* Allocate memory for scan result */ - scan_res = kmalloc(mem_reqd, GFP_KERNEL); - if (scan_res == NULL) { - SLSI_ERR_NODEV("Failed to allocate memory for scan result\n"); - return NULL; - } - - /* Exclude 1 byte for ie_data[1] */ - scan_res->scan_res_len = (sizeof(struct slsi_nl_scan_result_param) - 1) + ie_len; - scan_res->anqp_length = 0; - - get_monotonic_boottime(&ts); - scan_res->nl_scan_res.ts = (u64)TIMESPEC_TO_US(ts); - - ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, &mgmt->u.beacon.variable[0], ie_len); - if ((ssid_ie != NULL) && (ssid_ie[1] > 0) && (ssid_ie[1] < IEEE80211_MAX_SSID_LEN)) { - memcpy(scan_res->nl_scan_res.ssid, &ssid_ie[2], ssid_ie[1]); - scan_res->nl_scan_res.ssid[ssid_ie[1]] = '\0'; - } else { - scan_res->nl_scan_res.ssid[0] = '\0'; - } - - SLSI_ETHER_COPY(scan_res->nl_scan_res.bssid, mgmt->bssid); - scan_res->nl_scan_res.channel = fapi_get_u16(skb, u.mlme_scan_ind.channel_frequency) / 2; - scan_res->nl_scan_res.rssi = fapi_get_s16(skb, u.mlme_scan_ind.rssi); - scan_res->nl_scan_res.rtt = SLSI_GSCAN_RTT_UNSPECIFIED; - scan_res->nl_scan_res.rtt_sd = SLSI_GSCAN_RTT_UNSPECIFIED; - scan_res->nl_scan_res.beacon_period = mgmt->u.beacon.beacon_int; - scan_res->nl_scan_res.capability = mgmt->u.beacon.capab_info; - scan_res->nl_scan_res.ie_length = ie_len; - memcpy(scan_res->nl_scan_res.ie_data, ie, ie_len); - memcpy(scan_res->nl_scan_res.ie_data + ie_len, &hs2_id, sizeof(int)); - memcpy(scan_res->nl_scan_res.ie_data + ie_len + sizeof(int), &anqp_length, sizeof(u16)); - if (anqp_length) { - memcpy(scan_res->nl_scan_res.ie_data + ie_len + sizeof(u16) + sizeof(int), ie + ie_len, anqp_length); - scan_res->anqp_length = anqp_length + sizeof(u16) + sizeof(int); - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - slsi_gscan_scan_res_dump(scan_res); -#endif - - return scan_res; -} - -static void slsi_gscan_hash_add(struct slsi_dev *sdev, struct slsi_gscan_result *scan_res) -{ - u8 key = SLSI_GSCAN_GET_HASH_KEY(scan_res->nl_scan_res.bssid[5]); - struct netdev_vif *ndev_vif; - - ndev_vif = slsi_gscan_get_vif(sdev); - if (!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex)) - SLSI_WARN_NODEV("ndev_vif->scan_mutex is not locked\n"); - - scan_res->hnext = sdev->gscan_hash_table[key]; - sdev->gscan_hash_table[key] = scan_res; - - /* Update the total buffer consumed and number of scan results */ - sdev->buffer_consumed += scan_res->scan_res_len; - sdev->num_gscan_results++; -} - -static struct slsi_gscan_result *slsi_gscan_hash_get(struct slsi_dev *sdev, u8 *mac) -{ - struct slsi_gscan_result *temp; - struct netdev_vif *ndev_vif; - u8 key = SLSI_GSCAN_GET_HASH_KEY(mac[5]); - - ndev_vif = slsi_gscan_get_vif(sdev); - - if (!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex)) - SLSI_WARN_NODEV("ndev_vif->scan_mutex is not locked\n"); - - temp = sdev->gscan_hash_table[key]; - while (temp != NULL) { - if (memcmp(temp->nl_scan_res.bssid, mac, ETH_ALEN) == 0) - return temp; - temp = temp->hnext; - } - - return NULL; -} - -void slsi_gscan_hash_remove(struct slsi_dev *sdev, u8 *mac) -{ - u8 key = SLSI_GSCAN_GET_HASH_KEY(mac[5]); - struct slsi_gscan_result *curr; - struct slsi_gscan_result *prev; - struct netdev_vif *ndev_vif; - struct slsi_gscan_result *scan_res = NULL; - - ndev_vif = slsi_gscan_get_vif(sdev); - if (!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex)) - SLSI_WARN_NODEV("ndev_vif->scan_mutex is not locked\n"); - - if (sdev->gscan_hash_table[key] == NULL) - return; - - if (memcmp(sdev->gscan_hash_table[key]->nl_scan_res.bssid, mac, ETH_ALEN) == 0) { - scan_res = sdev->gscan_hash_table[key]; - sdev->gscan_hash_table[key] = sdev->gscan_hash_table[key]->hnext; - } else { - prev = sdev->gscan_hash_table[key]; - curr = prev->hnext; - - while (curr != NULL) { - if (memcmp(curr->nl_scan_res.bssid, mac, ETH_ALEN) == 0) { - scan_res = curr; - prev->hnext = curr->hnext; - break; - } - prev = curr; - curr = curr->hnext; - } - } - - if (scan_res) { - /* Update the total buffer consumed and number of scan results */ - sdev->buffer_consumed -= scan_res->scan_res_len; - sdev->num_gscan_results--; - kfree(scan_res); - } - - if (sdev->num_gscan_results < 0) - SLSI_ERR(sdev, "Wrong num_gscan_results: %d\n", sdev->num_gscan_results); -} - -int slsi_check_scan_result(struct slsi_dev *sdev, struct slsi_bucket *bucket, struct slsi_gscan_result *new_scan_res) -{ - struct slsi_gscan_result *scan_res; - - /* Check if the scan result for the same BSS already exists in driver buffer */ - scan_res = slsi_gscan_hash_get(sdev, new_scan_res->nl_scan_res.bssid); - if (scan_res == NULL) { /* New scan result */ - if ((sdev->buffer_consumed + new_scan_res->scan_res_len) >= SLSI_GSCAN_MAX_SCAN_CACHE_SIZE) { - SLSI_DBG2(sdev, SLSI_GSCAN, - "Scan buffer full, discarding scan result, buffer_consumed = %d, buffer_threshold = %d\n", - sdev->buffer_consumed, sdev->buffer_threshold); - - /* Scan buffer is full can't store anymore new results */ - return SLSI_DISCARD_SCAN_RESULT; - } - - return SLSI_KEEP_SCAN_RESULT; - } - - /* Even if scan buffer is full existing results can be replaced with the latest one */ - if (scan_res->scan_cycle == bucket->scan_cycle) - /* For the same scan cycle the result will be replaced only if the RSSI is better */ - if (new_scan_res->nl_scan_res.rssi < scan_res->nl_scan_res.rssi) - return SLSI_DISCARD_SCAN_RESULT; - - /* Remove the existing scan result */ - slsi_gscan_hash_remove(sdev, scan_res->nl_scan_res.bssid); - - return SLSI_KEEP_SCAN_RESULT; -} - -void slsi_gscan_handle_scan_result(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 scan_id, bool scan_done) -{ - struct slsi_gscan_result *scan_res = NULL; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_bucket *bucket; - u16 bucket_index; - int event_type = WIFI_SCAN_FAILED; - u16 anqp_length; - int hs2_network_id; - - if (!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex)) - SLSI_WARN_NODEV("ndev_vif->scan_mutex is not locked\n"); - - SLSI_NET_DBG_HEX(dev, SLSI_GSCAN, skb->data, skb->len, "mlme_scan_ind skb->len: %d\n", skb->len); - - bucket_index = scan_id - SLSI_GSCAN_SCAN_ID_START; - if (bucket_index >= SLSI_GSCAN_MAX_BUCKETS) { - SLSI_NET_ERR(dev, "Invalid bucket index: %d (scan_id = %#x)\n", bucket_index, scan_id); - goto out; - } - - bucket = &sdev->bucket[bucket_index]; - if (!bucket->used) { - SLSI_NET_DBG1(dev, SLSI_GSCAN, "Bucket is not active, index: %d (scan_id = %#x)\n", bucket_index, scan_id); - goto out; - } - - /* For scan_done indication - no need to store the results */ - if (scan_done) { - bucket->scan_cycle++; - bucket->gscan->num_scans++; - - SLSI_NET_DBG3(dev, SLSI_GSCAN, "scan done, scan_cycle = %d, num_scans = %d\n", - bucket->scan_cycle, bucket->gscan->num_scans); - - if (bucket->report_events & SLSI_REPORT_EVENTS_EACH_SCAN) - event_type = WIFI_SCAN_RESULTS_AVAILABLE; - if (bucket->gscan->num_scans % bucket->gscan->report_threshold_num_scans == 0) - event_type = WIFI_SCAN_THRESHOLD_NUM_SCANS; - if (sdev->buffer_consumed >= sdev->buffer_threshold) - event_type = WIFI_SCAN_THRESHOLD_PERCENT; - - if (event_type != WIFI_SCAN_FAILED) - slsi_vendor_event(sdev, SLSI_NL80211_SCAN_EVENT, &event_type, sizeof(event_type)); - - goto out; - } - - anqp_length = fapi_get_u16(skb, u.mlme_scan_ind.anqp_elements_length); - /* TODO new FAPI 3.c has mlme_scan_ind.network_block_id, use that when fapi is updated. */ - hs2_network_id = 1; - - scan_res = slsi_prepare_scan_result(skb, anqp_length, hs2_network_id); - if (scan_res == NULL) { - SLSI_NET_ERR(dev, "Failed to prepare scan result\n"); - goto out; - } - - /* Check for ePNO networks */ - if (fapi_get_u16(skb, u.mlme_scan_ind.preferrednetwork_ap)) { - if (anqp_length == 0) - slsi_vendor_event(sdev, SLSI_NL80211_EPNO_EVENT, - &scan_res->nl_scan_res, scan_res->scan_res_len); - else - slsi_vendor_event(sdev, SLSI_NL80211_HOTSPOT_MATCH, - &scan_res->nl_scan_res, scan_res->scan_res_len + scan_res->anqp_length); - } - - if (bucket->report_events & SLSI_REPORT_EVENTS_FULL_RESULTS) { - struct sk_buff *nlevent; - - SLSI_NET_DBG3(dev, SLSI_GSCAN, "report_events: SLSI_REPORT_EVENTS_FULL_RESULTS\n"); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - nlevent = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, scan_res->scan_res_len + 4, SLSI_NL80211_FULL_SCAN_RESULT_EVENT, GFP_KERNEL); -#else - nlevent = cfg80211_vendor_event_alloc(sdev->wiphy, scan_res->scan_res_len + 4, SLSI_NL80211_FULL_SCAN_RESULT_EVENT, GFP_KERNEL); -#endif - if (!nlevent) { - SLSI_ERR(sdev, "failed to allocate sbk of size:%d\n", scan_res->scan_res_len + 4); - kfree(scan_res); - goto out; - } - if (nla_put_u32(nlevent, GSCAN_ATTRIBUTE_SCAN_BUCKET_BIT, (1 << bucket_index)) || - nla_put(nlevent, GSCAN_ATTRIBUTE_SCAN_RESULTS, scan_res->scan_res_len, &scan_res->nl_scan_res)) { - SLSI_ERR(sdev, "failed to put data\n"); - kfree_skb(nlevent); - kfree(scan_res); - goto out; - } - cfg80211_vendor_event(nlevent, GFP_KERNEL); - } - - if (slsi_check_scan_result(sdev, bucket, scan_res) == SLSI_DISCARD_SCAN_RESULT) { - kfree(scan_res); - goto out; - } - slsi_gscan_hash_add(sdev, scan_res); - -out: - slsi_kfree_skb(skb); -} - -u8 slsi_gscan_get_scan_policy(enum wifi_band band) -{ - u8 scan_policy; - - switch (band) { - case WIFI_BAND_UNSPECIFIED: - scan_policy = FAPI_SCANPOLICY_ANY_RA; - break; - case WIFI_BAND_BG: - scan_policy = FAPI_SCANPOLICY_2_4GHZ; - break; - case WIFI_BAND_A: - scan_policy = (FAPI_SCANPOLICY_5GHZ | - FAPI_SCANPOLICY_NON_DFS); - break; - case WIFI_BAND_A_DFS: - scan_policy = (FAPI_SCANPOLICY_5GHZ | - FAPI_SCANPOLICY_DFS); - break; - case WIFI_BAND_A_WITH_DFS: - scan_policy = (FAPI_SCANPOLICY_5GHZ | - FAPI_SCANPOLICY_NON_DFS | - FAPI_SCANPOLICY_DFS); - break; - case WIFI_BAND_ABG: - scan_policy = (FAPI_SCANPOLICY_5GHZ | - FAPI_SCANPOLICY_NON_DFS | - FAPI_SCANPOLICY_2_4GHZ); - break; - case WIFI_BAND_ABG_WITH_DFS: - scan_policy = (FAPI_SCANPOLICY_5GHZ | - FAPI_SCANPOLICY_NON_DFS | - FAPI_SCANPOLICY_DFS | - FAPI_SCANPOLICY_2_4GHZ); - break; - default: - scan_policy = FAPI_SCANPOLICY_ANY_RA; - break; - } - - SLSI_DBG2_NODEV(SLSI_GSCAN, "Scan Policy: %#x\n", scan_policy); - - return scan_policy; -} - -static int slsi_gscan_add_read_params(struct slsi_nl_gscan_param *nl_gscan_param, const void *data, int len) -{ - int j = 0; - int type, tmp, tmp1, tmp2, k = 0; - const struct nlattr *iter, *iter1, *iter2; - struct slsi_nl_bucket_param *nl_bucket; - - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - - if (j >= SLSI_GSCAN_MAX_BUCKETS) - break; - - switch (type) { - case GSCAN_ATTRIBUTE_BASE_PERIOD: - if (nla_len(iter) != SLSI_NL_ATTRIBUTE_U32_LEN) - return -EINVAL; - nl_gscan_param->base_period = nla_get_u32(iter); - break; - case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN: - if (nla_len(iter) != SLSI_NL_ATTRIBUTE_U32_LEN) - return -EINVAL; - nl_gscan_param->max_ap_per_scan = nla_get_u32(iter); - break; - case GSCAN_ATTRIBUTE_REPORT_THRESHOLD: - if (nla_len(iter) != SLSI_NL_ATTRIBUTE_U32_LEN) - return -EINVAL; - nl_gscan_param->report_threshold_percent = nla_get_u32(iter); - break; - case GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS: - if (nla_len(iter) != SLSI_NL_ATTRIBUTE_U32_LEN) - return -EINVAL; - nl_gscan_param->report_threshold_num_scans = nla_get_u32(iter); - break; - case GSCAN_ATTRIBUTE_NUM_BUCKETS: - if (nla_len(iter) != SLSI_NL_ATTRIBUTE_U32_LEN) - return -EINVAL; - nl_gscan_param->num_buckets = nla_get_u32(iter); - break; - case GSCAN_ATTRIBUTE_CH_BUCKET_1: - case GSCAN_ATTRIBUTE_CH_BUCKET_2: - case GSCAN_ATTRIBUTE_CH_BUCKET_3: - case GSCAN_ATTRIBUTE_CH_BUCKET_4: - case GSCAN_ATTRIBUTE_CH_BUCKET_5: - case GSCAN_ATTRIBUTE_CH_BUCKET_6: - case GSCAN_ATTRIBUTE_CH_BUCKET_7: - case GSCAN_ATTRIBUTE_CH_BUCKET_8: - nla_for_each_nested(iter1, iter, tmp1) { - type = nla_type(iter1); - - nl_bucket = nl_gscan_param->nl_bucket; - - switch (type) { - case GSCAN_ATTRIBUTE_BUCKET_ID: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].bucket_index = nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_BUCKET_PERIOD: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].period = nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].num_channels = nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_BUCKET_CHANNELS: - nla_for_each_nested(iter2, iter1, tmp2) { - if (k >= SLSI_GSCAN_MAX_CHANNELS) - break; - - if (nla_len(iter2) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - - nl_bucket[j].channels[k].channel = nla_get_u32(iter2); - k++; - } - k = 0; - break; - case GSCAN_ATTRIBUTE_BUCKETS_BAND: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].band = nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_REPORT_EVENTS: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].report_events = nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_BUCKET_EXPONENT: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].exponent = nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].step_count = nla_get_u32(iter1); - break; - case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD: - if (nla_len(iter1) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) - return -EINVAL; - nl_bucket[j].max_period = nla_get_u32(iter1); - break; - default: - SLSI_ERR_NODEV("No ATTR_BUKTS_type - %x\n", type); - break; - } - } - j++; - break; - default: - SLSI_ERR_NODEV("No GSCAN_ATTR_CH_BUKT_type - %x\n", type); - break; - } - } - - return 0; -} - -int slsi_gscan_add_verify_params(struct slsi_nl_gscan_param *nl_gscan_param) -{ - int i; - - if ((nl_gscan_param->max_ap_per_scan < 0) || (nl_gscan_param->max_ap_per_scan > SLSI_GSCAN_MAX_AP_CACHE_PER_SCAN)) { - SLSI_ERR_NODEV("Invalid max_ap_per_scan: %d\n", nl_gscan_param->max_ap_per_scan); - return -EINVAL; - } - - if ((nl_gscan_param->report_threshold_percent < 0) || (nl_gscan_param->report_threshold_percent > SLSI_GSCAN_MAX_SCAN_REPORTING_THRESHOLD)) { - SLSI_ERR_NODEV("Invalid report_threshold_percent: %d\n", nl_gscan_param->report_threshold_percent); - return -EINVAL; - } - - if ((nl_gscan_param->num_buckets <= 0) || (nl_gscan_param->num_buckets > SLSI_GSCAN_MAX_BUCKETS)) { - SLSI_ERR_NODEV("Invalid num_buckets: %d\n", nl_gscan_param->num_buckets); - return -EINVAL; - } - - for (i = 0; i < nl_gscan_param->num_buckets; i++) { - if ((nl_gscan_param->nl_bucket[i].band == WIFI_BAND_UNSPECIFIED) && (nl_gscan_param->nl_bucket[i].num_channels == 0)) { - SLSI_ERR_NODEV("No band/channels provided for gscan: band = %d, num_channel = %d\n", - nl_gscan_param->nl_bucket[i].band, nl_gscan_param->nl_bucket[i].num_channels); - return -EINVAL; - } - - if (nl_gscan_param->nl_bucket[i].report_events > 4) { - SLSI_ERR_NODEV("Unsupported report event: report_event = %d\n", nl_gscan_param->nl_bucket[i].report_events); - return -EINVAL; - } - } - - return 0; -} - -void slsi_gscan_add_to_list(struct slsi_gscan **sdev_gscan, struct slsi_gscan *gscan) -{ - gscan->next = *sdev_gscan; - *sdev_gscan = gscan; -} - -int slsi_gscan_alloc_buckets(struct slsi_dev *sdev, struct slsi_gscan *gscan, int num_buckets) -{ - int i; - int bucket_index = 0; - int free_buckets = 0; - - for (i = 0; i < SLSI_GSCAN_MAX_BUCKETS; i++) - if (!sdev->bucket[i].used) - free_buckets++; - - if (num_buckets > free_buckets) { - SLSI_ERR_NODEV("Not enough free buckets, num_buckets = %d, free_buckets = %d\n", - num_buckets, free_buckets); - return -EINVAL; - } - - /* Allocate free buckets for the current gscan */ - for (i = 0; i < SLSI_GSCAN_MAX_BUCKETS; i++) - if (!sdev->bucket[i].used) { - sdev->bucket[i].used = true; - sdev->bucket[i].gscan = gscan; - gscan->bucket[bucket_index] = &sdev->bucket[i]; - bucket_index++; - if (bucket_index == num_buckets) - break; - } - - return 0; -} - -static void slsi_gscan_free_buckets(struct slsi_gscan *gscan) -{ - struct slsi_bucket *bucket; - int i; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "gscan = %p, num_buckets = %d\n", gscan, gscan->num_buckets); - - for (i = 0; i < gscan->num_buckets; i++) { - bucket = gscan->bucket[i]; - - SLSI_DBG2_NODEV(SLSI_GSCAN, "bucket = %p, used = %d, report_events = %d, scan_id = %#x, gscan = %p\n", - bucket, bucket->used, bucket->report_events, bucket->scan_id, bucket->gscan); - if (bucket->used) { - bucket->used = false; - bucket->report_events = 0; - bucket->gscan = NULL; - } - } -} - -void slsi_gscan_flush_scan_results(struct slsi_dev *sdev) -{ - struct netdev_vif *ndev_vif; - struct slsi_gscan_result *temp; - int i; - - ndev_vif = slsi_gscan_get_vif(sdev); - if (!ndev_vif) { - SLSI_WARN_NODEV("ndev_vif is NULL"); - return; - } - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - for (i = 0; i < SLSI_GSCAN_HASH_TABLE_SIZE; i++) - while (sdev->gscan_hash_table[i]) { - temp = sdev->gscan_hash_table[i]; - sdev->gscan_hash_table[i] = sdev->gscan_hash_table[i]->hnext; - sdev->num_gscan_results--; - sdev->buffer_consumed -= temp->scan_res_len; - kfree(temp); - } - - SLSI_DBG2(sdev, SLSI_GSCAN, "num_gscan_results: %d, buffer_consumed = %d\n", - sdev->num_gscan_results, sdev->buffer_consumed); - - if (sdev->num_gscan_results != 0) - SLSI_WARN_NODEV("sdev->num_gscan_results is not zero\n"); - - if (sdev->buffer_consumed != 0) - SLSI_WARN_NODEV("sdev->buffer_consumedis not zero\n"); - - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); -} - -static int slsi_gscan_add_mlme(struct slsi_dev *sdev, struct slsi_nl_gscan_param *nl_gscan_param, struct slsi_gscan *gscan) -{ - struct slsi_gscan_param gscan_param; - struct net_device *dev; - int ret = 0; - int i; -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - u8 mac_addr_mask[ETH_ALEN]; -#endif - - dev = slsi_gscan_get_netdev(sdev); - - if (!dev) { - SLSI_WARN_NODEV("dev is NULL\n"); - return -EINVAL; - } - - for (i = 0; i < nl_gscan_param->num_buckets; i++) { - u16 report_mode = 0; - - gscan_param.nl_bucket = &nl_gscan_param->nl_bucket[i]; /* current bucket */ - gscan_param.bucket = gscan->bucket[i]; - - if (gscan_param.bucket->report_events) { - if (gscan_param.bucket->report_events & SLSI_REPORT_EVENTS_EACH_SCAN) - report_mode |= FAPI_REPORTMODE_END_OF_SCAN_CYCLE; - if (gscan_param.bucket->report_events & SLSI_REPORT_EVENTS_FULL_RESULTS) - report_mode |= FAPI_REPORTMODE_REAL_TIME; - if (gscan_param.bucket->report_events & SLSI_REPORT_EVENTS_NO_BATCH) - report_mode |= FAPI_REPORTMODE_NO_BATCH; - } else { - report_mode = FAPI_REPORTMODE_RESERVED; - } - - if (report_mode == 0) { - SLSI_NET_ERR(dev, "Invalid report event value: %d\n", gscan_param.bucket->report_events); - return -EINVAL; - } - - /* In case of epno no_batch mode should be set. */ - if (sdev->epno_active) - report_mode |= FAPI_REPORTMODE_NO_BATCH; - -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - memset(mac_addr_mask, 0xFF, ETH_ALEN); - if (sdev->scan_addr_set == 1) { - for (i = 3; i < ETH_ALEN; i++) - mac_addr_mask[i] = 0x00; - ret = slsi_set_mac_randomisation_mask(sdev, mac_addr_mask); - if (ret) - sdev->scan_addr_set = 0; - } else - slsi_set_mac_randomisation_mask(sdev, mac_addr_mask); -#endif - ret = slsi_mlme_add_scan(sdev, - dev, - FAPI_SCANTYPE_GSCAN, - report_mode, - 0, /* n_ssids */ - NULL, /* ssids */ - nl_gscan_param->nl_bucket[i].num_channels, - NULL, /* ieee80211_channel */ - &gscan_param, - NULL, /* ies */ - 0, /* ies_len */ - false /* wait_for_ind */); - - if (ret != 0) { - SLSI_NET_ERR(dev, "Failed to add bucket: %d\n", i); - - /* Delete the scan those are already added */ - for (i = (i - 1); i >= 0; i--) - slsi_mlme_del_scan(sdev, dev, gscan->bucket[i]->scan_id, false); - break; - } - } - - return ret; -} - -static int slsi_gscan_add(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - int ret = 0; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct slsi_nl_gscan_param *nl_gscan_param = NULL; - struct slsi_gscan *gscan; - struct netdev_vif *ndev_vif; - int buffer_threshold; - int i; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_ADD_GSCAN\n"); - - if (!sdev) { - SLSI_WARN_NODEV("sdev is NULL\n"); - return -EINVAL; - } - - if (!slsi_dev_gscan_supported()) - return -ENOTSUPP; - - ndev_vif = slsi_gscan_get_vif(sdev); - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - /* Allocate memory for the received scan params */ - nl_gscan_param = kzalloc(sizeof(*nl_gscan_param), GFP_KERNEL); - if (nl_gscan_param == NULL) { - SLSI_ERR_NODEV("Failed for allocate memory for gscan params\n"); - ret = -ENOMEM; - goto exit; - } - - slsi_gscan_add_read_params(nl_gscan_param, data, len); - -#ifdef CONFIG_SCSC_WLAN_DEBUG - slsi_gscan_add_dump_params(nl_gscan_param); -#endif - - ret = slsi_gscan_add_verify_params(nl_gscan_param); - if (ret) { - /* After adding a hotlist a new gscan is added with 0 buckets - return success */ - if (nl_gscan_param->num_buckets == 0) { - kfree(nl_gscan_param); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return 0; - } - - goto exit; - } - - /* Allocate Memory for the new gscan */ - gscan = kzalloc(sizeof(*gscan), GFP_KERNEL); - if (gscan == NULL) { - SLSI_ERR_NODEV("Failed to allocate memory for gscan\n"); - ret = -ENOMEM; - goto exit; - } - - gscan->num_buckets = nl_gscan_param->num_buckets; - gscan->report_threshold_percent = nl_gscan_param->report_threshold_percent; - gscan->report_threshold_num_scans = nl_gscan_param->report_threshold_num_scans; - gscan->nl_bucket = nl_gscan_param->nl_bucket[0]; - - /* If multiple gscan is added; consider the lowest report_threshold_percent */ - buffer_threshold = (SLSI_GSCAN_MAX_SCAN_CACHE_SIZE * nl_gscan_param->report_threshold_percent) / 100; - if ((sdev->buffer_threshold == 0) || (buffer_threshold < sdev->buffer_threshold)) - sdev->buffer_threshold = buffer_threshold; - - ret = slsi_gscan_alloc_buckets(sdev, gscan, nl_gscan_param->num_buckets); - if (ret) - goto exit_with_gscan_free; - - for (i = 0; i < nl_gscan_param->num_buckets; i++) - gscan->bucket[i]->report_events = nl_gscan_param->nl_bucket[i].report_events; - - ret = slsi_gscan_add_mlme(sdev, nl_gscan_param, gscan); - if (ret) { - /* Free the buckets */ - slsi_gscan_free_buckets(gscan); - - goto exit_with_gscan_free; - } - - slsi_gscan_add_to_list(&sdev->gscan, gscan); - - goto exit; - -exit_with_gscan_free: - kfree(gscan); -exit: - kfree(nl_gscan_param); - - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return ret; -} - -static int slsi_gscan_del(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev; - struct netdev_vif *ndev_vif; - struct slsi_gscan *gscan; - int ret = 0; - int i; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_DEL_GSCAN\n"); - - dev = slsi_gscan_get_netdev(sdev); - if (!dev) { - SLSI_WARN_NODEV("dev is NULL\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - while (sdev->gscan != NULL) { - gscan = sdev->gscan; - - SLSI_DBG3(sdev, SLSI_GSCAN, "gscan = %p, num_buckets = %d\n", gscan, gscan->num_buckets); - - for (i = 0; i < gscan->num_buckets; i++) - if (gscan->bucket[i]->used) - slsi_mlme_del_scan(sdev, dev, gscan->bucket[i]->scan_id, false); - slsi_gscan_free_buckets(gscan); - sdev->gscan = gscan->next; - kfree(gscan); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - - slsi_gscan_flush_scan_results(sdev); - - sdev->buffer_threshold = 0; - - return ret; -} - -static int slsi_gscan_get_scan_results(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct sk_buff *skb; - struct slsi_gscan_result *scan_res; - struct nlattr *scan_hdr; - struct netdev_vif *ndev_vif; - int num_results = 0; - int mem_needed; - const struct nlattr *attr; - int nl_num_results = 0; - int ret = 0; - int temp; - int type; - int i; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_GET_SCAN_RESULTS\n"); - - /* Read the number of scan results need to be given */ - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - - switch (type) { - case GSCAN_ATTRIBUTE_NUM_OF_RESULTS: - if (nla_len(attr) != SLSI_NL_ATTRIBUTE_U32_LEN) - return -EINVAL; - nl_num_results = nla_get_u32(attr); - break; - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - break; - } - } - - ndev_vif = slsi_gscan_get_vif(sdev); - if (!ndev_vif) { - SLSI_WARN_NODEV("ndev_vif is NULL\n"); - return -EINVAL; - } - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - num_results = sdev->num_gscan_results; - - SLSI_DBG3(sdev, SLSI_GSCAN, "nl_num_results: %d, num_results = %d\n", nl_num_results, sdev->num_gscan_results); - - if (num_results == 0) { - SLSI_DBG1(sdev, SLSI_GSCAN, "No scan results available\n"); - /* Return value should be 0 for this scenario */ - goto exit; - } - - /* Find the number of results to return */ - if (num_results > nl_num_results) - num_results = nl_num_results; - - /* 12 bytes additional for scan_id, flags and num_resuls */ - mem_needed = num_results * sizeof(struct slsi_nl_scan_result_param) + 12; - - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed); - if (skb == NULL) { - SLSI_ERR_NODEV("skb alloc failed"); - ret = -ENOMEM; - goto exit; - } - - scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); - if (scan_hdr == NULL) { - kfree_skb(skb); - SLSI_ERR_NODEV("scan_hdr is NULL.\n"); - ret = -ENOMEM; - goto exit; - } - - nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, 0); - nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, 0); - nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results); - - for (i = 0; i < SLSI_GSCAN_HASH_TABLE_SIZE; i++) - while (sdev->gscan_hash_table[i]) { - scan_res = sdev->gscan_hash_table[i]; - sdev->gscan_hash_table[i] = sdev->gscan_hash_table[i]->hnext; - sdev->num_gscan_results--; - sdev->buffer_consumed -= scan_res->scan_res_len; - /* TODO: If IE is included then HAL is not able to parse the results */ - nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, sizeof(struct slsi_nl_scan_result_param), &scan_res->nl_scan_res); - kfree(scan_res); - num_results--; - if (num_results == 0) - goto out; - } -out: - nla_nest_end(skb, scan_hdr); - - ret = cfg80211_vendor_cmd_reply(skb); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return ret; -} - -void slsi_rx_rssi_report_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_rssi_monitor_evt event_data; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_ETHER_COPY(event_data.bssid, fapi_get_buff(skb, u.mlme_rssi_report_ind.bssid)); - event_data.rssi = fapi_get_s16(skb, u.mlme_rssi_report_ind.rssi); - SLSI_DBG3(sdev, SLSI_GSCAN, "RSSI threshold breached, Current RSSI for %pM= %d\n", event_data.bssid, event_data.rssi); - slsi_vendor_event(sdev, SLSI_NL80211_RSSI_REPORT_EVENT, &event_data, sizeof(event_data)); - slsi_kfree_skb(skb); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -#ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD -static int slsi_key_mgmt_set_pmk(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *pmk, int pmklen) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - int r = 0; - - if (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) { - SLSI_DBG3(sdev, SLSI_GSCAN, "Not required to set PMK for P2P client\n"); - return r; - } - SLSI_DBG3(sdev, SLSI_GSCAN, "SUBCMD_SET_PMK Received\n"); - - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(net_dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - r = slsi_mlme_set_pmk(sdev, net_dev, pmk, (u16)pmklen); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} -#endif - -static int slsi_set_bssid_blacklist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - int temp1; - int type; - const struct nlattr *attr; - u32 num_bssids = 0; - u8 i = 0; - int ret; - u8 *bssid = NULL; - struct cfg80211_acl_data *acl_data = NULL; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_SET_BSSID_BLACK_LIST\n"); - - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - if (!net_dev) { - SLSI_WARN_NODEV("net_dev is NULL\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(net_dev); - /*This subcmd can be issued in either connected or disconnected state. - * Hence using scan_mutex and not vif_mutex - */ - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - nla_for_each_attr(attr, data, len, temp1) { - type = nla_type(attr); - - switch (type) { - case GSCAN_ATTRIBUTE_NUM_BSSID: - if (acl_data) - break; - - num_bssids = nla_get_u32(attr); - acl_data = kmalloc(sizeof(*acl_data) + (sizeof(struct mac_address) * num_bssids), GFP_KERNEL); - if (!acl_data) { - ret = -ENOMEM; - goto exit; - } - acl_data->n_acl_entries = num_bssids; - break; - - case GSCAN_ATTRIBUTE_BLACKLIST_BSSID: - if (!acl_data) { - ret = -EINVAL; - goto exit; - } - bssid = (u8 *)nla_data(attr); - SLSI_ETHER_COPY(acl_data->mac_addrs[i].addr, bssid); - SLSI_DBG3_NODEV(SLSI_GSCAN, "mac_addrs[%d]:%pM)\n", i, acl_data->mac_addrs[i].addr); - i++; - break; - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - if (acl_data) { - acl_data->acl_policy = FAPI_ACLPOLICY_BLACKLIST; - ret = slsi_mlme_set_acl(sdev, net_dev, 0, acl_data); - if (ret) - SLSI_ERR_NODEV("Failed to set bssid blacklist\n"); - } else { - ret = -EINVAL; - } -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - kfree(acl_data); - return ret; -} - -static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ -#ifndef CONFIG_SCSC_WLAN_NAT_KEEPALIVE_DISABLE - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - - int temp; - int type; - const struct nlattr *attr; - u16 ip_pkt_len = 0; - u8 *ip_pkt = NULL, *src_mac_addr = NULL, *dst_mac_addr = NULL; - u32 period = 0; - struct slsi_peer *peer; - struct sk_buff *skb; - struct ethhdr *ehdr; - int r = 0; - u16 host_tag = 0; - u8 index = 0; - - SLSI_DBG3(sdev, SLSI_MLME, "SUBCMD_START_KEEPALIVE_OFFLOAD received\n"); - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(net_dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - SLSI_WARN_NODEV("ndev_vif is not activated\n"); - r = -EINVAL; - goto exit; - } - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) { - SLSI_WARN_NODEV("ndev_vif->vif_type is not FAPI_VIFTYPE_STATION\n"); - r = -EINVAL; - goto exit; - } - if (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED) { - SLSI_WARN_NODEV("ndev_vif->sta.vif_status is not SLSI_VIF_STATUS_CONNECTED\n"); - r = -EINVAL; - goto exit; - } - - peer = slsi_get_peer_from_qs(sdev, net_dev, SLSI_STA_PEER_QUEUESET); - if (!peer) { - SLSI_WARN_NODEV("peer is NULL\n"); - r = -EINVAL; - goto exit; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - - switch (type) { - case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: - ip_pkt_len = nla_get_u16(attr); - break; - - case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: - ip_pkt = (u8 *)nla_data(attr); - break; - - case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: - period = nla_get_u32(attr); - break; - - case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: - dst_mac_addr = (u8 *)nla_data(attr); - break; - - case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: - src_mac_addr = (u8 *)nla_data(attr); - break; - - case MKEEP_ALIVE_ATTRIBUTE_ID: - index = nla_get_u8(attr); - break; - - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - r = -EINVAL; - goto exit; - } - } - - /* Stop any existing request. This may fail if no request exists - * so ignore the return value - */ - slsi_mlme_send_frame_mgmt(sdev, net_dev, NULL, 0, - FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME, - FAPI_MESSAGETYPE_ANY_OTHER, - ndev_vif->sta.keepalive_host_tag[index - 1], 0, 0, 0); - - skb = slsi_alloc_skb_headroom(sizeof(struct ethhdr) + ip_pkt_len, GFP_KERNEL); - if (!skb) { - SLSI_WARN_NODEV("Memory allocation failed for skb\n"); - r = -ENOMEM; - goto exit; - } - - skb_reset_mac_header(skb); - skb_set_network_header(skb, sizeof(struct ethhdr)); - - /* Ethernet Header */ - ehdr = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr)); - - if (dst_mac_addr) - SLSI_ETHER_COPY(ehdr->h_dest, dst_mac_addr); - if (src_mac_addr) - SLSI_ETHER_COPY(ehdr->h_source, src_mac_addr); - ehdr->h_proto = cpu_to_be16(ETH_P_IP); - if (ip_pkt) - memcpy(skb_put(skb, ip_pkt_len), ip_pkt, ip_pkt_len); - - skb->dev = net_dev; - skb->protocol = ETH_P_IP; - skb->ip_summed = CHECKSUM_UNNECESSARY; - - /* Queueset 0 AC 0 */ - skb->queue_mapping = slsi_netif_get_peer_queue(0, 0); - - /* Enabling the "Don't Fragment" Flag in the IP Header */ - ip_hdr(skb)->frag_off |= htons(IP_DF); - - /* Calculation of IP header checksum */ - ip_hdr(skb)->check = 0; - ip_send_check(ip_hdr(skb)); - - host_tag = slsi_tx_mgmt_host_tag(sdev); - r = slsi_mlme_send_frame_data(sdev, net_dev, skb, FAPI_MESSAGETYPE_ANY_OTHER, host_tag, - 0, (period * 1000)); - if (r == 0) - ndev_vif->sta.keepalive_host_tag[index - 1] = host_tag; - else - slsi_kfree_skb(skb); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -#else - SLSI_DBG3_NODEV(SLSI_MLME, "SUBCMD_START_KEEPALIVE_OFFLOAD received\n"); - SLSI_DBG3_NODEV(SLSI_MLME, "NAT Keep Alive Feature is disabled\n"); - return -EOPNOTSUPP; - -#endif -} - -static int slsi_stop_keepalive_offload(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ -#ifndef CONFIG_SCSC_WLAN_NAT_KEEPALIVE_DISABLE - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - int r = 0; - int temp; - int type; - const struct nlattr *attr; - u8 index = 0; - - SLSI_DBG3(sdev, SLSI_MLME, "SUBCMD_STOP_KEEPALIVE_OFFLOAD received\n"); - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(net_dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - SLSI_WARN(sdev, "VIF is not activated\n"); - r = -EINVAL; - goto exit; - } - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) { - SLSI_WARN(sdev, "Not a STA VIF\n"); - r = -EINVAL; - goto exit; - } - if (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED) { - SLSI_WARN(sdev, "VIF is not connected\n"); - r = -EINVAL; - goto exit; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - - switch (type) { - case MKEEP_ALIVE_ATTRIBUTE_ID: - index = nla_get_u8(attr); - break; - - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - r = -EINVAL; - goto exit; - } - } - - r = slsi_mlme_send_frame_mgmt(sdev, net_dev, NULL, 0, FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME, - FAPI_MESSAGETYPE_ANY_OTHER, ndev_vif->sta.keepalive_host_tag[index - 1], 0, 0, 0); - ndev_vif->sta.keepalive_host_tag[index - 1] = 0; - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -#else - SLSI_DBG3_NODEV(SLSI_MLME, "SUBCMD_STOP_KEEPALIVE_OFFLOAD received\n"); - SLSI_DBG3_NODEV(SLSI_MLME, "NAT Keep Alive Feature is disabled\n"); - return -EOPNOTSUPP; - -#endif -} - -static inline int slsi_epno_ssid_list_get(struct slsi_dev *sdev, - struct slsi_epno_ssid_param *epno_ssid_params, const struct nlattr *outer) -{ - int type, tmp; - u8 epno_auth; - u8 len = 0; - const struct nlattr *inner; - - nla_for_each_nested(inner, outer, tmp) { - type = nla_type(inner); - switch (type) { - case SLSI_ATTRIBUTE_EPNO_FLAGS: - epno_ssid_params->flags |= nla_get_u16(inner); - break; - case SLSI_ATTRIBUTE_EPNO_AUTH: - epno_auth = nla_get_u8(inner); - if (epno_auth & SLSI_EPNO_AUTH_FIELD_WEP_OPEN) - epno_ssid_params->flags |= FAPI_EPNOPOLICY_AUTH_OPEN; - else if (epno_auth & SLSI_EPNO_AUTH_FIELD_WPA_PSK) - epno_ssid_params->flags |= FAPI_EPNOPOLICY_AUTH_PSK; - else if (epno_auth & SLSI_EPNO_AUTH_FIELD_WPA_EAP) - epno_ssid_params->flags |= FAPI_EPNOPOLICY_AUTH_EAPOL; - break; - case SLSI_ATTRIBUTE_EPNO_SSID_LEN: - len = nla_get_u8(inner); - if (len <= 32) { - epno_ssid_params->ssid_len = len; - } else { - SLSI_ERR(sdev, "SSID too long %d\n", len); - return -EINVAL; - } - break; - case SLSI_ATTRIBUTE_EPNO_SSID: - memcpy(epno_ssid_params->ssid, nla_data(inner), len); - break; - default: - SLSI_WARN(sdev, "Ignoring unknown type:%d\n", type); - } - } - return 0; -} - -static int slsi_set_epno_ssid(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - int r = 0; - int tmp, tmp1, type, num = 0; - const struct nlattr *outer, *iter; - u8 i = 0; - struct slsi_epno_ssid_param *epno_ssid_params; - struct slsi_epno_param *epno_params; - - SLSI_DBG3(sdev, SLSI_GSCAN, "SUBCMD_SET_EPNO_LIST Received\n"); - - if (!slsi_dev_epno_supported()) - return -EOPNOTSUPP; - - epno_params = kmalloc((sizeof(*epno_params) + (sizeof(*epno_ssid_params) * SLSI_GSCAN_MAX_EPNO_SSIDS)), - GFP_KERNEL); - if (!epno_params) { - SLSI_ERR(sdev, "Mem alloc fail\n"); - return -ENOMEM; - } - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(net_dev); - nla_for_each_attr(iter, data, len, tmp1) { - type = nla_type(iter); - switch (type) { - case SLSI_ATTRIBUTE_EPNO_MINIMUM_5G_RSSI: - epno_params->min_5g_rssi = nla_get_u16(iter); - break; - case SLSI_ATTRIBUTE_EPNO_MINIMUM_2G_RSSI: - epno_params->min_2g_rssi = nla_get_u16(iter); - break; - case SLSI_ATTRIBUTE_EPNO_INITIAL_SCORE_MAX: - epno_params->initial_score_max = nla_get_u16(iter); - break; - case SLSI_ATTRIBUTE_EPNO_CUR_CONN_BONUS: - epno_params->current_connection_bonus = nla_get_u8(iter); - break; - case SLSI_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS: - epno_params->same_network_bonus = nla_get_u8(iter); - break; - case SLSI_ATTRIBUTE_EPNO_SECURE_BONUS: - epno_params->secure_bonus = nla_get_u8(iter); - break; - case SLSI_ATTRIBUTE_EPNO_5G_BONUS: - epno_params->band_5g_bonus = nla_get_u8(iter); - break; - case SLSI_ATTRIBUTE_EPNO_SSID_LIST: - nla_for_each_nested(outer, iter, tmp) { - epno_ssid_params = &epno_params->epno_ssid[i]; - epno_ssid_params->flags = 0; - r = slsi_epno_ssid_list_get(sdev, epno_ssid_params, outer); - if (r) - goto exit; - i++; - } - break; - case SLSI_ATTRIBUTE_EPNO_SSID_NUM: - num = nla_get_u8(iter); - if (num > SLSI_GSCAN_MAX_EPNO_SSIDS) { - SLSI_ERR(sdev, "Cannot support %d SSIDs. max %d\n", num, SLSI_GSCAN_MAX_EPNO_SSIDS); - r = -EINVAL; - goto exit; - } - epno_params->num_networks = num; - break; - default: - SLSI_ERR(sdev, "Invalid attribute %d\n", type); - r = -EINVAL; - goto exit; - } - } - - if (i != num) { - SLSI_ERR(sdev, "num_ssid %d does not match ssids sent %d\n", num, i); - r = -EINVAL; - goto exit; - } - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - r = slsi_mlme_set_pno_list(sdev, num, epno_params, NULL); - if (r == 0) - sdev->epno_active = (num != 0); - else - sdev->epno_active = false; - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - kfree(epno_params); - return r; -} - -static int slsi_set_hs_params(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - int r = 0; - int tmp, tmp1, tmp2, type, num = 0; - const struct nlattr *outer, *inner, *iter; - u8 i = 0; - struct slsi_epno_hs2_param *epno_hs2_params_array; - struct slsi_epno_hs2_param *epno_hs2_params; - - SLSI_DBG3(sdev, SLSI_GSCAN, "SUBCMD_SET_HS_LIST Received\n"); - - if (!slsi_dev_epno_supported()) - return -EOPNOTSUPP; - - epno_hs2_params_array = kmalloc(sizeof(*epno_hs2_params_array) * SLSI_GSCAN_MAX_EPNO_HS2_PARAM, GFP_KERNEL); - if (!epno_hs2_params_array) { - SLSI_ERR(sdev, "Mem alloc fail\n"); - return -ENOMEM; - } - - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(net_dev); - - nla_for_each_attr(iter, data, len, tmp2) { - type = nla_type(iter); - switch (type) { - case SLSI_ATTRIBUTE_EPNO_HS_PARAM_LIST: - nla_for_each_nested(outer, iter, tmp) { - epno_hs2_params = &epno_hs2_params_array[i]; - i++; - nla_for_each_nested(inner, outer, tmp1) { - type = nla_type(inner); - - switch (type) { - case SLSI_ATTRIBUTE_EPNO_HS_ID: - epno_hs2_params->id = (u32)nla_get_u32(inner); - break; - case SLSI_ATTRIBUTE_EPNO_HS_REALM: - memcpy(epno_hs2_params->realm, nla_data(inner), 256); - break; - case SLSI_ATTRIBUTE_EPNO_HS_CONSORTIUM_IDS: - memcpy(epno_hs2_params->roaming_consortium_ids, nla_data(inner), 16 * 8); - break; - case SLSI_ATTRIBUTE_EPNO_HS_PLMN: - memcpy(epno_hs2_params->plmn, nla_data(inner), 3); - break; - default: - SLSI_WARN(sdev, "Ignoring unknown type:%d\n", type); - } - } - } - break; - case SLSI_ATTRIBUTE_EPNO_HS_NUM: - num = nla_get_u8(iter); - if (num > SLSI_GSCAN_MAX_EPNO_HS2_PARAM) { - SLSI_ERR(sdev, "Cannot support %d SSIDs. max %d\n", num, SLSI_GSCAN_MAX_EPNO_SSIDS); - r = -EINVAL; - goto exit; - } - break; - default: - SLSI_ERR(sdev, "Invalid attribute %d\n", type); - r = -EINVAL; - goto exit; - } - } - if (i != num) { - SLSI_ERR(sdev, "num_ssid %d does not match ssids sent %d\n", num, i); - r = -EINVAL; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - r = slsi_mlme_set_pno_list(sdev, num, NULL, epno_hs2_params_array); - if (r == 0) - sdev->epno_active = true; - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - kfree(epno_hs2_params_array); - return r; -} - -static int slsi_reset_hs_params(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - int r; - - SLSI_DBG3(sdev, SLSI_GSCAN, "SUBCMD_RESET_HS_LIST Received\n"); - - if (!slsi_dev_epno_supported()) - return -EOPNOTSUPP; - - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(net_dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - r = slsi_mlme_set_pno_list(sdev, 0, NULL, NULL); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - sdev->epno_active = false; - return r; -} - -static int slsi_set_rssi_monitor(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev; - struct netdev_vif *ndev_vif; - int r = 0; - int temp; - int type; - const struct nlattr *attr; - s8 min_rssi = 0, max_rssi = 0; - u16 enable = 0; - - SLSI_DBG3(sdev, SLSI_GSCAN, "Recd RSSI monitor command\n"); - - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - if (net_dev == NULL) { - SLSI_ERR(sdev, "netdev is NULL!!\n"); - return -ENODEV; - } - - ndev_vif = netdev_priv(net_dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - SLSI_ERR(sdev, "Vif not activated\n"); - r = -EINVAL; - goto exit; - } - if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) { - SLSI_ERR(sdev, "Not a STA vif\n"); - r = -EINVAL; - goto exit; - } - if (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED) { - SLSI_ERR(sdev, "STA vif not connected\n"); - r = -EINVAL; - goto exit; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_RSSI_MONITOR_ATTRIBUTE_START: - enable = (u16)nla_get_u8(attr); - break; - case SLSI_RSSI_MONITOR_ATTRIBUTE_MIN_RSSI: - min_rssi = nla_get_s8(attr); - break; - case SLSI_RSSI_MONITOR_ATTRIBUTE_MAX_RSSI: - max_rssi = nla_get_s8(attr); - break; - default: - r = -EINVAL; - goto exit; - } - } - if (min_rssi > max_rssi) { - SLSI_ERR(sdev, "Invalid params, min_rssi= %d ,max_rssi = %d\n", min_rssi, max_rssi); - r = -EINVAL; - goto exit; - } - r = slsi_mlme_set_rssi_monitor(sdev, net_dev, enable, min_rssi, max_rssi); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return r; -} - -#ifdef CONFIG_SCSC_WLAN_DEBUG -void slsi_lls_debug_dump_stats(struct slsi_dev *sdev, struct slsi_lls_radio_stat *radio_stat, - struct slsi_lls_iface_stat *iface_stat, u8 *buf, int buf_len, int num_of_radios) -{ - int i, j; - - for (j = 0; j < num_of_radios; j++) { - SLSI_DBG3(sdev, SLSI_GSCAN, "radio_stat====\n"); - SLSI_DBG3(sdev, SLSI_GSCAN, "\tradio_id : %d, on_time : %d, tx_time : %d, rx_time : %d," - "on_time_scan : %d, num_channels : %d\n", radio_stat->radio, radio_stat->on_time, - radio_stat->tx_time, radio_stat->rx_time, radio_stat->on_time_scan, - radio_stat->num_channels); - - radio_stat = (struct slsi_lls_radio_stat *)((u8 *)radio_stat + sizeof(struct slsi_lls_radio_stat) + - (sizeof(struct slsi_lls_channel_stat) * radio_stat->num_channels)); - } - SLSI_DBG3(sdev, SLSI_GSCAN, "iface_stat====\n"); - SLSI_DBG3(sdev, SLSI_GSCAN, "\tiface %p info : (mode : %d, mac_addr : %pM, state : %d, roaming : %d," - " capabilities : %d, ssid : %s, bssid : %pM, ap_country_str : [%d%d%d])\trssi_data : %d\n", - iface_stat->iface, iface_stat->info.mode, iface_stat->info.mac_addr, iface_stat->info.state, - iface_stat->info.roaming, iface_stat->info.capabilities, iface_stat->info.ssid, - iface_stat->info.bssid, iface_stat->info.ap_country_str[0], iface_stat->info.ap_country_str[1], - iface_stat->info.ap_country_str[2], iface_stat->rssi_data); - - SLSI_DBG3(sdev, SLSI_GSCAN, "\tnum_peers %d\n", iface_stat->num_peers); - for (i = 0; i < iface_stat->num_peers; i++) { - SLSI_DBG3(sdev, SLSI_GSCAN, "\t\tpeer_mac_address %pM\n", iface_stat->peer_info[i].peer_mac_address); - } - - SLSI_DBG_HEX(sdev, SLSI_GSCAN, buf, buf_len, "return buffer\n"); -} -#endif - -static int slsi_lls_set_stats(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *net_dev = NULL; - struct netdev_vif *ndev_vif = NULL; - int temp; - int type; - const struct nlattr *attr; - u32 mpdu_size_threshold = 0; - u32 aggr_stat_gathering = 0; - int r = 0, i; - - if (!slsi_dev_lls_supported()) - return -EOPNOTSUPP; - - if (slsi_is_test_mode_enabled()) { - SLSI_WARN(sdev, "not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - - switch (type) { - case LLS_ATTRIBUTE_SET_MPDU_SIZE_THRESHOLD: - mpdu_size_threshold = nla_get_u32(attr); - break; - - case LLS_ATTRIBUTE_SET_AGGR_STATISTICS_GATHERING: - aggr_stat_gathering = nla_get_u32(attr); - break; - - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - r = -EINVAL; - } - } - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - /* start Statistics measurements in Firmware */ - (void)slsi_mlme_start_link_stats_req(sdev, mpdu_size_threshold, aggr_stat_gathering); - - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - if (net_dev) { - ndev_vif = netdev_priv(net_dev); - for (i = 0; i < SLSI_LLS_AC_MAX; i++) { - ndev_vif->rx_packets[i] = 0; - ndev_vif->tx_packets[i] = 0; - ndev_vif->tx_no_ack[i] = 0; - } - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return 0; -} - -static int slsi_lls_clear_stats(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int temp; - int type; - const struct nlattr *attr; - u32 stats_clear_req_mask = 0; - u32 stop_req = 0; - int r = 0, i; - struct net_device *net_dev = NULL; - struct netdev_vif *ndev_vif = NULL; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - - switch (type) { - case LLS_ATTRIBUTE_CLEAR_STOP_REQUEST_MASK: - stats_clear_req_mask = nla_get_u32(attr); - SLSI_DBG3(sdev, SLSI_GSCAN, "stats_clear_req_mask:%u\n", stats_clear_req_mask); - break; - - case LLS_ATTRIBUTE_CLEAR_STOP_REQUEST: - stop_req = nla_get_u32(attr); - SLSI_DBG3(sdev, SLSI_GSCAN, "stop_req:%u\n", stop_req); - break; - - default: - SLSI_ERR(sdev, "Unknown attribute:%d\n", type); - r = -EINVAL; - } - } - - /* stop_req = 0 : clear the stats which are flaged 0 - * stop_req = 1 : clear the stats which are flaged 1 - */ - if (!stop_req) - stats_clear_req_mask = ~stats_clear_req_mask; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - (void)slsi_mlme_stop_link_stats_req(sdev, stats_clear_req_mask); - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - if (net_dev) { - ndev_vif = netdev_priv(net_dev); - for (i = 0; i < SLSI_LLS_AC_MAX; i++) { - ndev_vif->rx_packets[i] = 0; - ndev_vif->tx_packets[i] = 0; - ndev_vif->tx_no_ack[i] = 0; - } - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return 0; -} - -static u32 slsi_lls_ie_to_cap(const u8 *ies, int ies_len) -{ - u32 capabilities = 0; - const u8 *ie_data; - const u8 *ie; - int ie_len; - - if (!ies || ies_len == 0) { - SLSI_ERR_NODEV("no ie[&%p %d]\n", ies, ies_len); - return 0; - } - ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ies_len); - if (ie) { - ie_len = ie[1]; - ie_data = &ie[2]; - if ((ie_len >= 4) && (ie_data[3] & SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED)) - capabilities |= SLSI_LLS_CAPABILITY_INTERWORKING; - if ((ie_len >= 7) && (ie_data[6] & 0x01)) /* Bit48: UTF-8 ssid */ - capabilities |= SLSI_LLS_CAPABILITY_SSID_UTF8; - } - - ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, SLSI_WLAN_OUI_TYPE_WFA_HS20_IND, ies, ies_len); - if (ie) - capabilities |= SLSI_LLS_CAPABILITY_HS20; - return capabilities; -} - -static void slsi_lls_iface_sta_stats(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, - struct slsi_lls_iface_stat *iface_stat) -{ - int i; - struct slsi_lls_interface_link_layer_info *lls_info = &iface_stat->info; - enum slsi_lls_peer_type peer_type; - struct slsi_peer *peer; - const u8 *ie_data, *ie; - u8 ie_len; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - - if (ndev_vif->ifnum == SLSI_NET_INDEX_WLAN) { - lls_info->mode = SLSI_LLS_INTERFACE_STA; - peer_type = SLSI_LLS_PEER_AP; - } else { - lls_info->mode = SLSI_LLS_INTERFACE_P2P_CLIENT; - peer_type = SLSI_LLS_PEER_P2P_GO; - } - - switch (ndev_vif->sta.vif_status) { - case SLSI_VIF_STATUS_CONNECTING: - lls_info->state = SLSI_LLS_AUTHENTICATING; - break; - case SLSI_VIF_STATUS_CONNECTED: - lls_info->state = SLSI_LLS_ASSOCIATED; - break; - default: - lls_info->state = SLSI_LLS_DISCONNECTED; - } - lls_info->roaming = ndev_vif->sta.roam_in_progress ? - SLSI_LLS_ROAMING_ACTIVE : SLSI_LLS_ROAMING_IDLE; - - iface_stat->info.capabilities = 0; - lls_info->ssid[0] = 0; - if (ndev_vif->sta.sta_bss) { - ie = cfg80211_find_ie(WLAN_EID_SSID, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - if (ie) { - ie_len = ie[1]; - ie_data = &ie[2]; - memcpy(lls_info->ssid, ie_data, ie_len); - lls_info->ssid[ie_len] = 0; - } - SLSI_ETHER_COPY(lls_info->bssid, ndev_vif->sta.sta_bss->bssid); - ie = cfg80211_find_ie(WLAN_EID_COUNTRY, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - if (ie) { - ie_data = &ie[2]; - memcpy(lls_info->ap_country_str, ie_data, 3); - iface_stat->peer_info[0].capabilities |= SLSI_LLS_CAPABILITY_COUNTRY; - } - } - - peer = ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET]; /* connected AP */ - if (peer && peer->valid && peer->assoc_ie && peer->assoc_resp_ie) { - iface_stat->info.capabilities |= slsi_lls_ie_to_cap(peer->assoc_ie->data, peer->assoc_ie->len); - if (peer->capabilities & WLAN_CAPABILITY_PRIVACY) { - iface_stat->peer_info[0].capabilities |= SLSI_LLS_CAPABILITY_PROTECTED; - iface_stat->info.capabilities |= SLSI_LLS_CAPABILITY_PROTECTED; - } - if (peer->qos_enabled) { - iface_stat->peer_info[0].capabilities |= SLSI_LLS_CAPABILITY_QOS; - iface_stat->info.capabilities |= SLSI_LLS_CAPABILITY_QOS; - } - iface_stat->peer_info[0].capabilities |= slsi_lls_ie_to_cap(peer->assoc_resp_ie->data, peer->assoc_resp_ie->len); - - SLSI_ETHER_COPY(iface_stat->peer_info[0].peer_mac_address, peer->address); - iface_stat->peer_info[0].type = peer_type; - iface_stat->num_peers = 1; - } - - for (i = MAP_AID_TO_QS(SLSI_TDLS_PEER_INDEX_MIN); i <= MAP_AID_TO_QS(SLSI_TDLS_PEER_INDEX_MAX); i++) { - peer = ndev_vif->peer_sta_record[i]; - if (peer && peer->valid) { - SLSI_ETHER_COPY(iface_stat->peer_info[iface_stat->num_peers].peer_mac_address, peer->address); - iface_stat->peer_info[iface_stat->num_peers].type = SLSI_LLS_PEER_TDLS; - if (peer->qos_enabled) - iface_stat->peer_info[iface_stat->num_peers].capabilities |= SLSI_LLS_CAPABILITY_QOS; - iface_stat->peer_info[iface_stat->num_peers].num_rate = 0; - iface_stat->num_peers++; - } - } -} - -static void slsi_lls_iface_ap_stats(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, struct slsi_lls_iface_stat *iface_stat) -{ - enum slsi_lls_peer_type peer_type = SLSI_LLS_PEER_INVALID; - struct slsi_peer *peer; - int i; - struct net_device *dev; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - - /* We are AP/GO, so we advertize our own country. */ - memcpy(iface_stat->info.ap_country_str, iface_stat->info.country_str, 3); - - if (ndev_vif->ifnum == SLSI_NET_INDEX_WLAN) { - iface_stat->info.mode = SLSI_LLS_INTERFACE_SOFTAP; - peer_type = SLSI_LLS_PEER_STA; - } else if (ndev_vif->ifnum == SLSI_NET_INDEX_P2PX_SWLAN) { - dev = sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]; - if (SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif)) { - iface_stat->info.mode = SLSI_LLS_INTERFACE_P2P_GO; - peer_type = SLSI_LLS_PEER_P2P_CLIENT; - } - } - - for (i = MAP_AID_TO_QS(SLSI_PEER_INDEX_MIN); i <= MAP_AID_TO_QS(SLSI_PEER_INDEX_MAX); i++) { - peer = ndev_vif->peer_sta_record[i]; - if (peer && peer->valid) { - SLSI_ETHER_COPY(iface_stat->peer_info[iface_stat->num_peers].peer_mac_address, peer->address); - iface_stat->peer_info[iface_stat->num_peers].type = peer_type; - iface_stat->peer_info[iface_stat->num_peers].num_rate = 0; - if (peer->qos_enabled) - iface_stat->peer_info[iface_stat->num_peers].capabilities = SLSI_LLS_CAPABILITY_QOS; - iface_stat->num_peers++; - } - } - - memcpy(iface_stat->info.ssid, ndev_vif->ap.ssid, ndev_vif->ap.ssid_len); - iface_stat->info.ssid[ndev_vif->ap.ssid_len] = 0; - if (ndev_vif->ap.privacy) - iface_stat->info.capabilities |= SLSI_LLS_CAPABILITY_PROTECTED; - if (ndev_vif->ap.qos_enabled) - iface_stat->info.capabilities |= SLSI_LLS_CAPABILITY_QOS; -} - -static void slsi_lls_iface_stat_fill(struct slsi_dev *sdev, - struct net_device *net_dev, - struct slsi_lls_iface_stat *iface_stat) -{ - int i; - struct netdev_vif *ndev_vif; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_AC_RETRIES, { SLSI_TRAFFIC_Q_BE + 1, 0 } }, - { SLSI_PSID_UNIFI_AC_RETRIES, { SLSI_TRAFFIC_Q_BK + 1, 0 } }, - { SLSI_PSID_UNIFI_AC_RETRIES, { SLSI_TRAFFIC_Q_VI + 1, 0 } }, - { SLSI_PSID_UNIFI_AC_RETRIES, { SLSI_TRAFFIC_Q_VO + 1, 0 } }, - { SLSI_PSID_UNIFI_BEACON_RECEIVED, {0, 0} }, - { SLSI_PSID_UNIFI_PS_LEAKY_AP, {0, 0} }, - { SLSI_PSID_UNIFI_RSSI, {0, 0} } }; - - iface_stat->iface = NULL; - iface_stat->info.mode = SLSI_LLS_INTERFACE_UNKNOWN; - iface_stat->info.country_str[0] = sdev->device_config.domain_info.regdomain->alpha2[0]; - iface_stat->info.country_str[1] = sdev->device_config.domain_info.regdomain->alpha2[1]; - iface_stat->info.country_str[2] = ' '; /* 3rd char of our country code is ASCII */ - - for (i = 0; i < SLSI_LLS_AC_MAX; i++) - iface_stat->ac[i].ac = SLSI_LLS_AC_MAX; - - if (!net_dev) - return; - - ndev_vif = netdev_priv(net_dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) - goto exit; - - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - slsi_lls_iface_sta_stats(sdev, ndev_vif, iface_stat); - } else if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) { - slsi_lls_iface_ap_stats(sdev, ndev_vif, iface_stat); - SLSI_ETHER_COPY(iface_stat->info.bssid, net_dev->dev_addr); - } - SLSI_ETHER_COPY(iface_stat->info.mac_addr, net_dev->dev_addr); - - mibrsp.dataLength = 10 * sizeof(get_values) / sizeof(get_values[0]); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes for interface MIBs\n", mibrsp.dataLength); - goto exit; - } - - values = slsi_read_mibs(sdev, net_dev, get_values, sizeof(get_values) / sizeof(get_values[0]), &mibrsp); - if (!values) - goto exit; - - for (i = 0; i < SLSI_LLS_AC_MAX; i++) { - if (values[i].type == SLSI_MIB_TYPE_UINT) { - iface_stat->ac[i].ac = slsi_fapi_to_android_traffic_q(i); - iface_stat->ac[i].retries = values[i].u.uintValue; - iface_stat->ac[i].rx_mpdu = ndev_vif->rx_packets[i]; - iface_stat->ac[i].tx_mpdu = ndev_vif->tx_packets[i]; - iface_stat->ac[i].mpdu_lost = ndev_vif->tx_no_ack[i]; - } else { - SLSI_WARN(sdev, "LLS: expected datatype 1 but received %d\n", values[i].type); - } - } - - if (values[4].type == SLSI_MIB_TYPE_UINT) - iface_stat->beacon_rx = values[4].u.uintValue; - - if (values[5].type == SLSI_MIB_TYPE_UINT) { - iface_stat->leaky_ap_detected = values[5].u.uintValue; - iface_stat->leaky_ap_guard_time = 5; /* 5 milli sec. As mentioned in lls document */ - } - - if (values[6].type == SLSI_MIB_TYPE_INT) - iface_stat->rssi_data = values[6].u.intValue; - -exit: - kfree(values); - kfree(mibrsp.data); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -void slsi_check_num_radios(struct slsi_dev *sdev) -{ - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_RADIO_SCAN_TIME, { 1, 0 } } }; - - if (slsi_is_test_mode_enabled()) { - SLSI_WARN(sdev, "not supported in WlanLite mode\n"); - return; - } - - /* Expect each mib length in response is <= 15 So assume 15 bytes for each MIB */ - mibrsp.dataLength = 15 * ARRAY_SIZE(get_values); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - sdev->lls_num_radio = 0; - return; - } - - values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp); - if (!values) { - sdev->lls_num_radio = 0; - } else { - sdev->lls_num_radio = values[0].type == SLSI_MIB_TYPE_NONE ? 1 : 2; - kfree(values); - } - - kfree(mibrsp.data); -} - -static void slsi_lls_radio_stat_fill(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_lls_radio_stat *radio_stat, - int max_chan_count, int radio_index, int twoorfive) -{ - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_data supported_chan_mib = { 0, NULL }; - struct slsi_mib_value *values = NULL; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_RADIO_SCAN_TIME, { radio_index, 0 } }, - { SLSI_PSID_UNIFI_RADIO_RX_TIME, { radio_index, 0 } }, - { SLSI_PSID_UNIFI_RADIO_TX_TIME, { radio_index, 0 } }, - { SLSI_PSID_UNIFI_RADIO_ON_TIME, { radio_index, 0 } }, - { SLSI_PSID_UNIFI_SUPPORTED_CHANNELS, { 0, 0 } } }; - u32 *radio_data[] = {&radio_stat->on_time_scan, &radio_stat->rx_time, - &radio_stat->tx_time, &radio_stat->on_time}; - int i, j, chan_count, chan_start, k; - - radio_stat->radio = radio_index; - - /* Expect each mib length in response is <= 15 So assume 15 bytes for each MIB */ - mibrsp.dataLength = 15 * sizeof(get_values) / sizeof(get_values[0]); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (mibrsp.data == NULL) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - return; - } - values = slsi_read_mibs(sdev, NULL, get_values, sizeof(get_values) / sizeof(get_values[0]), &mibrsp); - if (!values) - goto exit_with_mibrsp; - - for (i = 0; i < (sizeof(get_values) / sizeof(get_values[0])) - 1; i++) { - if (values[i].type == SLSI_MIB_TYPE_UINT) { - *radio_data[i] = values[i].u.uintValue; - } else { - SLSI_ERR(sdev, "invalid type. iter:%d", i); - } - } - if (values[4].type != SLSI_MIB_TYPE_OCTET) { - SLSI_ERR(sdev, "Supported_Chan invalid type."); - goto exit_with_values; - } - - supported_chan_mib = values[4].u.octetValue; - for (j = 0; j < supported_chan_mib.dataLength / 2; j++) { - struct slsi_lls_channel_info *radio_chan; - - chan_start = supported_chan_mib.data[j * 2]; - chan_count = supported_chan_mib.data[j * 2 + 1]; - if (radio_stat->num_channels + chan_count > max_chan_count) - chan_count = max_chan_count - radio_stat->num_channels; - if (chan_start == 1 && (twoorfive & BIT(0))) { /* for 2.4GHz */ - for (k = 0; k < chan_count; k++) { - radio_chan = &radio_stat->channels[radio_stat->num_channels + k].channel; - if (k + chan_start == 14) - radio_chan->center_freq = 2484; - else - radio_chan->center_freq = 2407 + (chan_start + k) * 5; - radio_chan->width = SLSI_LLS_CHAN_WIDTH_20; - } - radio_stat->num_channels += chan_count; - } else if (chan_start != 1 && (twoorfive & BIT(1))) { - /* for 5GHz */ - for (k = 0; k < chan_count; k++) { - radio_chan = &radio_stat->channels[radio_stat->num_channels + k].channel; - radio_chan->center_freq = 5000 + (chan_start + (k * 4)) * 5; - radio_chan->width = SLSI_LLS_CHAN_WIDTH_20; - } - radio_stat->num_channels += chan_count; - } - } -exit_with_values: - kfree(values); -exit_with_mibrsp: - kfree(mibrsp.data); -} - -static int slsi_lls_fill(struct slsi_dev *sdev, u8 **src_buf) -{ - struct net_device *net_dev = NULL; - struct slsi_lls_radio_stat *radio_stat; - struct slsi_lls_radio_stat *radio_stat_temp; - struct slsi_lls_iface_stat *iface_stat; - int buf_len = 0; - int max_chan_count = 0; - u8 *buf; - int num_of_radios_supported; - int i = 0; - int radio_type[2] = {BIT(0), BIT(1)}; - - if (sdev->lls_num_radio == 0) { - slsi_check_num_radios(sdev); - if (sdev->lls_num_radio == 0) - return -EIO; - } - - num_of_radios_supported = sdev->lls_num_radio; - net_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - - if (sdev->wiphy->bands[NL80211_BAND_2GHZ]) - max_chan_count = sdev->wiphy->bands[NL80211_BAND_2GHZ]->n_channels; - if (sdev->wiphy->bands[NL80211_BAND_5GHZ]) - max_chan_count += sdev->wiphy->bands[NL80211_BAND_5GHZ]->n_channels; - buf_len = (int)((num_of_radios_supported * sizeof(struct slsi_lls_radio_stat)) - + sizeof(struct slsi_lls_iface_stat) - + sizeof(u8) - + (sizeof(struct slsi_lls_peer_info) * SLSI_ADHOC_PEER_CONNECTIONS_MAX) - + (sizeof(struct slsi_lls_channel_stat) * max_chan_count)); - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) { - SLSI_ERR(sdev, "No mem. Size:%d\n", buf_len); - return -ENOMEM; - } - buf[0] = num_of_radios_supported; - *src_buf = buf; - iface_stat = (struct slsi_lls_iface_stat *)(buf + sizeof(u8)); - slsi_lls_iface_stat_fill(sdev, net_dev, iface_stat); - - radio_stat = (struct slsi_lls_radio_stat *)(buf + sizeof(u8) + sizeof(struct slsi_lls_iface_stat) + - (sizeof(struct slsi_lls_peer_info) * iface_stat->num_peers)); - radio_stat_temp = radio_stat; - if (num_of_radios_supported == 1) { - radio_type[0] = BIT(0) | BIT(1); - slsi_lls_radio_stat_fill(sdev, net_dev, radio_stat, max_chan_count, 0, radio_type[0]); - radio_stat = (struct slsi_lls_radio_stat *)((u8 *)radio_stat + sizeof(struct slsi_lls_radio_stat) + - (sizeof(struct slsi_lls_channel_stat) * radio_stat->num_channels)); - } else { - for (i = 1; i <= num_of_radios_supported ; i++) { - slsi_lls_radio_stat_fill(sdev, net_dev, radio_stat, max_chan_count, i, radio_type[i - 1]); - radio_stat = (struct slsi_lls_radio_stat *)((u8 *)radio_stat + - sizeof(struct slsi_lls_radio_stat) + (sizeof(struct slsi_lls_channel_stat) - * radio_stat->num_channels)); - } - } -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (slsi_dev_llslogs_supported()) - slsi_lls_debug_dump_stats(sdev, radio_stat_temp, iface_stat, buf, buf_len, num_of_radios_supported); -#endif - return buf_len; -} - -static int slsi_lls_get_stats(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret; - u8 *buf = NULL; - int buf_len; - - if (!slsi_dev_lls_supported()) - return -EOPNOTSUPP; - - if (slsi_is_test_mode_enabled()) { - SLSI_WARN(sdev, "not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - - if (!sdev) { - SLSI_ERR(sdev, "sdev is Null\n"); - return -EINVAL; - } - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - /* In case of lower layer failure do not read LLS MIBs */ - if (sdev->mlme_blocked) - buf_len = -EIO; - else - buf_len = slsi_lls_fill(sdev, &buf); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - - if (buf_len > 0) { - ret = slsi_vendor_cmd_reply(wiphy, buf, buf_len); - if (ret) - SLSI_ERR_NODEV("vendor cmd reply failed (err:%d)\n", ret); - } else { - ret = buf_len; - } - kfree(buf); - return ret; -} - -static int slsi_gscan_set_oui(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - int ret = 0; - -#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION - - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - struct netdev_vif *ndev_vif; - int temp; - int type; - const struct nlattr *attr; - u8 scan_oui[6]; - - memset(&scan_oui, 0, 6); - - if (!dev) { - SLSI_ERR(sdev, "dev is NULL!!\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - sdev->scan_addr_set = 0; - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_NL_ATTRIBUTE_PNO_RANDOM_MAC_OUI: - { - if (nla_len(attr) != 3) { - ret = -EINVAL; - break; - } - memcpy(&scan_oui, nla_data(attr), 3); - memcpy(sdev->scan_mac_addr, scan_oui, 6); - sdev->scan_addr_set = 1; - break; - } - default: - ret = -EINVAL; - SLSI_ERR(sdev, "Invalid type : %d\n", type); - break; - } - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); -#endif - return ret; -} - -static int slsi_get_feature_set(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - u32 feature_set = 0; - int ret = 0; - - SLSI_DBG3_NODEV(SLSI_GSCAN, "\n"); - - feature_set |= SLSI_WIFI_HAL_FEATURE_RSSI_MONITOR; - feature_set |= SLSI_WIFI_HAL_FEATURE_CONTROL_ROAMING; - feature_set |= SLSI_WIFI_HAL_FEATURE_TDLS | SLSI_WIFI_HAL_FEATURE_TDLS_OFFCHANNEL; -#ifndef CONFIG_SCSC_WLAN_NAT_KEEPALIVE_DISABLE - feature_set |= SLSI_WIFI_HAL_FEATURE_MKEEP_ALIVE; -#endif -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING - feature_set |= SLSI_WIFI_HAL_FEATURE_LOGGER; -#endif - if (slsi_dev_gscan_supported()) - feature_set |= SLSI_WIFI_HAL_FEATURE_GSCAN; - if (slsi_dev_lls_supported()) - feature_set |= SLSI_WIFI_HAL_FEATURE_LINK_LAYER_STATS; - if (slsi_dev_epno_supported()) - feature_set |= SLSI_WIFI_HAL_FEATURE_HAL_EPNO; - if (slsi_dev_nan_supported(SDEV_FROM_WIPHY(wiphy))) - feature_set |= SLSI_WIFI_HAL_FEATURE_NAN; - if (slsi_dev_rtt_supported()) { - feature_set |= SLSI_WIFI_HAL_FEATURE_D2D_RTT; - feature_set |= SLSI_WIFI_HAL_FEATURE_D2AP_RTT; - } - - ret = slsi_vendor_cmd_reply(wiphy, &feature_set, sizeof(feature_set)); - - return ret; -} - -static int slsi_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp; - int type; - const struct nlattr *attr; - char country_code[SLSI_COUNTRY_CODE_LEN]; - - SLSI_DBG3(sdev, SLSI_GSCAN, "Received country code command\n"); - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_NL_ATTRIBUTE_COUNTRY_CODE: - { - if (nla_len(attr) < (SLSI_COUNTRY_CODE_LEN - 1)) { - ret = -EINVAL; - SLSI_ERR(sdev, "Insufficient Country Code Length : %d\n", nla_len(attr)); - return ret; - } - memcpy(country_code, nla_data(attr), (SLSI_COUNTRY_CODE_LEN - 1)); - break; - } - default: - ret = -EINVAL; - SLSI_ERR(sdev, "Invalid type : %d\n", type); - return ret; - } - } - ret = slsi_set_country_update_regd(sdev, country_code, SLSI_COUNTRY_CODE_LEN); - if (ret < 0) - SLSI_ERR(sdev, "Set country failed ret:%d\n", ret); - return ret; -} - -static int slsi_apf_read_filter(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - int ret = 0; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - u8 *host_dst; - int datalen; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_APF_READ_FILTER\n"); - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - if (!sdev->device_config.fw_apf_supported) { - SLSI_WARN(sdev, "APF not supported by the firmware.\n"); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return -ENOTSUPP; - } - - ret = slsi_mlme_read_apf_request(sdev, dev, &host_dst, &datalen); - if (!ret) - ret = slsi_vendor_cmd_reply(wiphy, host_dst, datalen); - - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return ret; -} - -static int slsi_apf_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - int ret = 0; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - struct sk_buff *nl_skb; - struct nlattr *nlattr_start; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_APF_GET_CAPABILITIES\n"); - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - if (!sdev->device_config.fw_apf_supported) { - SLSI_WARN(sdev, "APF not supported by the firmware.\n"); - ret = -ENOTSUPP; - goto exit; - } - memset(&sdev->device_config.apf_cap, 0, sizeof(struct slsi_apf_capabilities)); - - ret = slsi_mib_get_apf_cap(sdev, dev); - if (ret != 0) { - SLSI_ERR(sdev, "Failed to read mib\n"); - goto exit; - } - SLSI_DBG3(sdev, SLSI_GSCAN, "APF version: %d Max_Length:%d\n", sdev->device_config.apf_cap.version, - sdev->device_config.apf_cap.max_length); - nl_skb = cfg80211_vendor_cmd_alloc_reply_skb(sdev->wiphy, NLMSG_DEFAULT_SIZE); - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - ret = -ENOMEM; - goto exit; - } - - nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); - if (!nlattr_start) { - SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - ret = -EINVAL; - goto exit; - } - - ret = nla_put_u16(nl_skb, SLSI_APF_ATTR_VERSION, sdev->device_config.apf_cap.version); - ret |= nla_put_u16(nl_skb, SLSI_APF_ATTR_MAX_LEN, sdev->device_config.apf_cap.max_length); - if (ret) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", ret); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(nl_skb); - if (ret) - SLSI_ERR(sdev, "apf_get_capabilities cfg80211_vendor_cmd_reply failed :%d\n", ret); -exit: - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return ret; -} - -static int slsi_apf_set_filter(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - int ret = 0; - int temp; - int type; - const struct nlattr *attr; - u32 program_len = 0; - u8 *program = NULL; - - SLSI_DBG3(sdev, SLSI_GSCAN, "Received apf_set_filter command\n"); - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - if (!sdev->device_config.fw_apf_supported) { - SLSI_WARN(sdev, "APF not supported by the firmware.\n"); - ret = -ENOTSUPP; - goto exit; - } - - if (!dev) { - SLSI_ERR(sdev, "dev is NULL!!\n"); - ret = -EINVAL; - goto exit; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_APF_ATTR_PROGRAM_LEN: - { - program_len = nla_get_u32(attr); - kfree(program); - program = kmalloc(program_len, GFP_KERNEL); - if (!program) { - ret = -ENOMEM; - goto exit; - } - break; - } - case SLSI_APF_ATTR_PROGRAM: - { - memcpy(program, (u8 *)nla_data(attr), program_len); - break; - } - default: - SLSI_ERR(sdev, "Invalid type : %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - ret = slsi_mlme_install_apf_request(sdev, dev, program, program_len); - if (ret < 0) { - SLSI_ERR(sdev, "apf_set_filter failed ret:%d\n", ret); - ret = -EINVAL; - goto exit; - } -exit: - kfree(program); - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return ret; -} - -static int slsi_rtt_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_rtt_capabilities rtt_cap; - int ret = 0; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_GET_RTT_CAPABILITIES\n"); - if (!slsi_dev_rtt_supported()) { - SLSI_WARN(sdev, "RTT not supported.\n"); - return -ENOTSUPP; - } - memset(&rtt_cap, 0, sizeof(struct slsi_rtt_capabilities)); - - ret = slsi_mib_get_rtt_cap(sdev, dev, &rtt_cap); - if (ret != 0) { - SLSI_ERR(sdev, "Failed to read mib\n"); - return ret; - } - ret = slsi_vendor_cmd_reply(wiphy, &rtt_cap, sizeof(struct slsi_rtt_capabilities)); - if (ret) - SLSI_ERR_NODEV("rtt_get_capabilities vendor cmd reply failed (err = %d)\n", ret); - return ret; -} - -static int slsi_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - int r, type, j = 0; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); -#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE - struct netdev_vif *ndev_vif; -#endif - struct net_device *dev = wdev->netdev; - struct slsi_rtt_config *nl_rtt_params; - const struct nlattr *iter, *outer, *inner; - u8 source_addr[ETH_ALEN]; - int tmp, tmp1, tmp2; - u16 rtt_id = 0; - u8 num_devices = 0; - u16 rtt_peer = SLSI_RTT_PEER_AP; - u16 vif_idx = 0; - u16 channel_freq = 0; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_RTT_RANGE_START\n"); - if (!slsi_dev_rtt_supported()) { - SLSI_ERR(sdev, "RTT not supported.\n"); - return WIFI_HAL_ERROR_NOT_SUPPORTED; - } - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case SLSI_RTT_ATTRIBUTE_TARGET_CNT: - num_devices = nla_get_u8(iter); - SLSI_DBG1_NODEV(SLSI_GSCAN, "Target cnt %d\n", num_devices); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_ID: - rtt_id = nla_get_u16(iter); - SLSI_DBG1_NODEV(SLSI_GSCAN, "Target id %d\n", rtt_id); - break; - default: - SLSI_ERR_NODEV("Unexpected RTT attribute:type - %d\n", type); - break; - } - } - if (!num_devices) { - SLSI_ERR_NODEV("No device found for rtt configuration!\n"); - return -EINVAL; - } - /* Allocate memory for the received config params */ - nl_rtt_params = kcalloc(num_devices, sizeof(*nl_rtt_params), GFP_KERNEL); - if (!nl_rtt_params) { - SLSI_ERR_NODEV("Failed for allocate memory for config rtt_param\n"); - return -ENOMEM; - } - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case SLSI_RTT_ATTRIBUTE_TARGET_INFO: - nla_for_each_nested(outer, iter, tmp1) { - nla_for_each_nested(inner, outer, tmp2) { - switch (nla_type(inner)) { - case SLSI_RTT_ATTRIBUTE_TARGET_MAC: - memcpy(nl_rtt_params[j].peer_addr, nla_data(inner), ETH_ALEN); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_TYPE: - nl_rtt_params[j].type = nla_get_u16(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_PEER: - rtt_peer = nla_get_u16(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_CHAN_FREQ: - channel_freq = nla_get_u16(inner); - nl_rtt_params[j].channel_freq = channel_freq * 2; - break; - case SLSI_RTT_ATTRIBUTE_TARGET_PERIOD: - nl_rtt_params[j].burst_period = nla_get_u8(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_NUM_BURST: - nl_rtt_params[j].num_burst = nla_get_u8(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST: - nl_rtt_params[j].num_frames_per_burst = nla_get_u8(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR: - nl_rtt_params[j].num_retries_per_ftmr = nla_get_u8(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_BURST_DURATION: - nl_rtt_params[j].burst_duration = nla_get_u8(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_PREAMBLE: - nl_rtt_params[j].preamble = nla_get_u16(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_BW: - nl_rtt_params[j].bw = nla_get_u16(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_LCI: - nl_rtt_params[j].LCI_request = nla_get_u16(inner); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_LCR: - nl_rtt_params[j].LCR_request = nla_get_u16(inner); - break; - default: - SLSI_ERR_NODEV("Unknown RTT INFO ATTRIBUTE type: %d\n", type); - break; - } - } - j++; - } - break; - default: - SLSI_ERR_NODEV("No ATTRIBUTE_Target cnt - %d\n", type); - break; - } - } - - SLSI_ETHER_COPY(source_addr, dev->dev_addr); - - if (rtt_peer == SLSI_RTT_PEER_NAN) { -#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE - if (!slsi_dev_nan_supported(sdev)) { - SLSI_ERR(sdev, "NAN not supported(mib:%d)\n", sdev->nan_enabled); - kfree(nl_rtt_params); - return WIFI_HAL_ERROR_NOT_SUPPORTED; - } - ndev_vif = netdev_priv(dev); - if (ndev_vif->activated) { - vif_idx = ndev_vif->vif_type; - } else { - SLSI_ERR(sdev, "NAN vif not activated\n"); - kfree(nl_rtt_params); - return -EINVAL; - } -#else - SLSI_ERR(sdev, "NAN not enabled\n"); - return -ENOTSUPP; -#endif - } - r = slsi_mlme_add_range_req(sdev, num_devices, nl_rtt_params, rtt_id, vif_idx, source_addr); - if (r) { - r = -EINVAL; - SLSI_ERR_NODEV("Failed to set rtt config\n"); - } else { - sdev->rtt_vif[rtt_id] = vif_idx; - SLSI_DBG1_NODEV(SLSI_GSCAN, "Successfully set rtt config\n"); - } - kfree(nl_rtt_params); - return r; -} - -int slsi_tx_rate_calc(struct sk_buff *nl_skb, u16 fw_rate, int res, bool tx_rate) -{ - u8 preamble; - const u32 fw_rate_idx_to_80211_rate[] = { 0, 10, 20, 55, 60, 90, 110, 120, 180, 240, 360, 480, 540 }; - u32 data_rate = 0; - u32 mcs = 0, nss = 0; - u32 chan_bw_idx = 0; - int gi_idx; - - preamble = (fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) >> 14; - if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_NON_HT_SELECTED) { - u16 fw_rate_idx = fw_rate & SLSI_FW_API_RATE_INDEX_FIELD; - - if (fw_rate > 0 && fw_rate_idx < ARRAY_SIZE(fw_rate_idx_to_80211_rate)) - data_rate = fw_rate_idx_to_80211_rate[fw_rate_idx]; - } else if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_HT_SELECTED) { - nss = (SLSI_FW_API_RATE_HT_NSS_FIELD & fw_rate) >> 6; - chan_bw_idx = (fw_rate & SLSI_FW_API_RATE_BW_FIELD) >> 9; - gi_idx = ((fw_rate & SLSI_FW_API_RATE_SGI) == SLSI_FW_API_RATE_SGI) ? 1 : 0; - mcs = SLSI_FW_API_RATE_HT_MCS_FIELD & fw_rate; - if ((chan_bw_idx < 2) && (mcs <= 7)) { - data_rate = (nss + 1) * slsi_rates_table[chan_bw_idx][gi_idx][mcs]; - } else if (mcs == 32 && chan_bw_idx == 1) { - if (gi_idx == 1) - data_rate = (nss + 1) * 67; - else - data_rate = (nss + 1) * 60; - } else { - SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x, nss : %d\n", - fw_rate, chan_bw_idx, mcs, nss); - } - } else if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_VHT_SELECTED) { - /* report vht rate in legacy units and not as mcs index. reason: upper layers may still be not - * updated with vht msc table. - */ - chan_bw_idx = (fw_rate & SLSI_FW_API_RATE_BW_FIELD) >> 9; - gi_idx = ((fw_rate & SLSI_FW_API_RATE_SGI) == SLSI_FW_API_RATE_SGI) ? 1 : 0; - /* Calculate NSS --> bits 6 to 4*/ - nss = (SLSI_FW_API_RATE_VHT_NSS_FIELD & fw_rate) >> 4; - mcs = SLSI_FW_API_RATE_VHT_MCS_FIELD & fw_rate; - /* Bandwidth (BW): 0x0= 20 MHz, 0x1= 40 MHz, 0x2= 80 MHz, 0x3= 160/ 80+80 MHz. 0x3 is not supported */ - if ((chan_bw_idx <= 2) && (mcs <= 9)) - data_rate = (nss + 1) * slsi_rates_table[chan_bw_idx][gi_idx][mcs]; - else - SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x,nss : %d\n", - fw_rate, chan_bw_idx, mcs, nss); - if (nss > 1) - nss += 1; - } - - if (tx_rate) { - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_TX_PREAMBLE, preamble); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_TX_NSS, nss); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_TX_BW, chan_bw_idx); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_TX_MCS, mcs); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_TX_RATE, data_rate); - } else { - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RX_PREAMBLE, preamble); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RX_NSS, nss); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RX_BW, chan_bw_idx); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RX_MCS, mcs); - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RX_RATE, data_rate); - } - return res; -} - -void slsi_rx_range_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u32 i, tm; - u16 rtt_entry_count = fapi_get_u16(skb, u.mlme_range_ind.entries); - u16 rtt_id = fapi_get_u16(skb, u.mlme_range_ind.rtt_id); - u32 tmac = fapi_get_u32(skb, u.mlme_range_ind.spare_3); - int data_len = fapi_get_datalen(skb); - u8 *ip_ptr, *start_ptr; - u16 tx_data, rx_data; - struct sk_buff *nl_skb; - int res = 0; - struct nlattr *nlattr_nested; - struct timespec ts; - u64 tkernel; - u8 rep_cnt = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, - SLSI_NL80211_RTT_RESULT_EVENT, GFP_KERNEL); -#else - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_RTT_RESULT_EVENT, - GFP_KERNEL); -#endif -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(SLSI_NL80211_RTT_RESULT_EVENT), SLSI_NL80211_RTT_RESULT_EVENT); -#endif - - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - goto exit; - } - - ip_ptr = fapi_get_data(skb); - start_ptr = fapi_get_data(skb); - res |= nla_put_u16(nl_skb, SLSI_RTT_ATTRIBUTE_RESULT_CNT, rtt_entry_count); - res |= nla_put_u16(nl_skb, SLSI_RTT_ATTRIBUTE_TARGET_ID, rtt_id); - res |= nla_put_u8(nl_skb, SLSI_RTT_ATTRIBUTE_RESULTS_PER_TARGET, 1); - for (i = 0; i < rtt_entry_count; i++) { - nlattr_nested = nla_nest_start(nl_skb, SLSI_RTT_ATTRIBUTE_RESULT); - if (!nlattr_nested) { - SLSI_ERR(sdev, "Error in nla_nest_start\n"); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - goto exit; - } - ip_ptr += 7; /*skip first 7 bytes for fapi_ie_generic */ - res |= nla_put(nl_skb, SLSI_RTT_EVENT_ATTR_ADDR, ETH_ALEN, ip_ptr); - ip_ptr += 6; - res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_BURST_NUM, *ip_ptr++); - res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_MEASUREMENT_NUM, *ip_ptr++); - res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_SUCCESS_NUM, *ip_ptr++); - res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_NUM_PER_BURST_PEER, *ip_ptr++); - res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_STATUS, *ip_ptr); - ip_ptr += 2; - res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_RETRY_AFTER_DURATION, *ip_ptr++); - res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_TYPE, *ip_ptr); - ip_ptr += 2; - res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RSSI, *ip_ptr); - ip_ptr += 2; - res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RSSI_SPREAD, *ip_ptr); - ip_ptr += 2; - memcpy(&tx_data, ip_ptr, 2); - res = slsi_tx_rate_calc(nl_skb, tx_data, res, 1); - ip_ptr += 2; - memcpy(&rx_data, ip_ptr, 2); - res = slsi_tx_rate_calc(nl_skb, rx_data, res, 0); - ip_ptr += 2; - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RTT, *ip_ptr); - ip_ptr += 4; - res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RTT_SD, *ip_ptr); - ip_ptr += 2; - res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RTT_SPREAD, *ip_ptr); - ip_ptr += 2; - get_monotonic_boottime(&ts); - tkernel = (u64)TIMESPEC_TO_US(ts); - tm = *ip_ptr; - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_TIMESTAMP_US, tkernel - (tmac - tm)); - ip_ptr += 4; - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_DISTANCE_MM, *ip_ptr); - ip_ptr += 4; - res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_DISTANCE_SD_MM, *ip_ptr); - ip_ptr += 4; - res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_BURST_DURATION_MSN, *ip_ptr++); - res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_NEGOTIATED_BURST_NUM, *ip_ptr++); - for (rep_cnt = 0; rep_cnt < 2; rep_cnt++) { - if (ip_ptr - start_ptr < data_len && ip_ptr[0] == WLAN_EID_MEASURE_REPORT) { - if (ip_ptr[4] == 8) /*LCI Element*/ - res |= nla_put(nl_skb, SLSI_RTT_EVENT_ATTR_LCI, - ip_ptr[1] + 2, ip_ptr); - else if (ip_ptr[4] == 11) /*LCR element */ - res |= nla_put(nl_skb, SLSI_RTT_EVENT_ATTR_LCR, - ip_ptr[1] + 2, ip_ptr); - ip_ptr += ip_ptr[1] + 2; - } - } - nla_nest_end(nl_skb, nlattr_nested); - } - SLSI_DBG_HEX(sdev, SLSI_GSCAN, fapi_get_data(skb), fapi_get_datalen(skb), "range indication skb buffer:\n"); - if (res) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); - kfree_skb(nl_skb); - goto exit; - } - cfg80211_vendor_event(nl_skb, GFP_KERNEL); -exit: - slsi_kfree_skb(skb); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -void slsi_rx_range_done_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 rtt_id = fapi_get_u16(skb, u.mlme_range_ind.rtt_id); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(SLSI_NL80211_RTT_COMPLETE_EVENT), SLSI_NL80211_RTT_COMPLETE_EVENT); -#endif - slsi_vendor_event(sdev, SLSI_NL80211_RTT_COMPLETE_EVENT, &rtt_id, sizeof(rtt_id)); - slsi_kfree_skb(skb); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -static int slsi_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - int temp, ret, r = 1, j = 0, type; - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - u8 *addr; - const struct nlattr *iter; - u16 num_devices = 0, rtt_id = 0; - - SLSI_DBG1_NODEV(SLSI_GSCAN, "RTT_SUBCMD_CANCEL_CONFIG\n"); - if (!slsi_dev_rtt_supported()) { - SLSI_WARN(sdev, "RTT not supported.\n"); - return -ENOTSUPP; - } - nla_for_each_attr(iter, data, len, temp) { - type = nla_type(iter); - switch (type) { - case SLSI_RTT_ATTRIBUTE_TARGET_CNT: - num_devices = nla_get_u16(iter); - SLSI_DBG1_NODEV(SLSI_GSCAN, "Target cnt %d\n", num_devices); - break; - case SLSI_RTT_ATTRIBUTE_TARGET_ID: - rtt_id = nla_get_u16(iter); - SLSI_DBG1_NODEV(SLSI_GSCAN, "Target id %d\n", rtt_id); - break; - default: - SLSI_ERR_NODEV("No ATTRIBUTE_Target cnt - %d\n", type); - break; - } - } - /* Allocate memory for the received mac addresses */ - if (num_devices) { - addr = kzalloc(ETH_ALEN * num_devices, GFP_KERNEL); - if (!addr) { - SLSI_ERR_NODEV("Failed for allocate memory for mac addresses\n"); - ret = -ENOMEM; - return ret; - } - nla_for_each_attr(iter, data, len, temp) { - type = nla_type(iter); - if (type == SLSI_RTT_ATTRIBUTE_TARGET_MAC) { - memcpy(&addr[j], nla_data(iter), ETH_ALEN); - j++; - } else { - SLSI_ERR_NODEV("No ATTRIBUTE_MAC - %d\n", type); - } - } - - r = slsi_mlme_del_range_req(sdev, dev, num_devices, addr, rtt_id); - kfree(addr); - } - if (r) - SLSI_ERR_NODEV("Failed to cancel rtt config\n"); - return r; -} - -static int slsi_configure_nd_offload(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - struct netdev_vif *ndev_vif; - int ret = 0; - int temp; - int type; - const struct nlattr *attr; - u8 nd_offload_enabled = 0; - - SLSI_DBG3(sdev, SLSI_GSCAN, "Received nd_offload command\n"); - - if (!dev) { - SLSI_ERR(sdev, "dev is NULL!!\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_DBG3(sdev, SLSI_GSCAN, "vif error\n"); - ret = -EPERM; - goto exit; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_NL_ATTRIBUTE_ND_OFFLOAD_VALUE: - { - nd_offload_enabled = nla_get_u8(attr); - break; - } - default: - SLSI_ERR(sdev, "Invalid type : %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - ndev_vif->sta.nd_offload_enabled = nd_offload_enabled; - ret = slsi_mlme_set_ipv6_address(sdev, dev); - if (ret < 0) { - SLSI_ERR(sdev, "Configure nd_offload failed ret:%d nd_offload_enabled: %d\n", ret, nd_offload_enabled); - ret = -EINVAL; - goto exit; - } -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return ret; -} - -static int slsi_get_roaming_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - struct netdev_vif *ndev_vif; - int ret = 0; - struct slsi_mib_value *values = NULL; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_ROAM_BLACKLIST_SIZE, { 0, 0 } } }; - u32 max_blacklist_size = 0; - u32 max_whitelist_size = 0; - struct sk_buff *nl_skb; - struct nlattr *nlattr_start; - - if (!dev) { - SLSI_ERR(sdev, "dev is NULL!!\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - mibrsp.dataLength = 10; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - ret = -ENOMEM; - goto exit; - } - values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp); - if (values && (values[0].type == SLSI_MIB_TYPE_UINT || values[0].type == SLSI_MIB_TYPE_INT)) - max_blacklist_size = values[0].u.uintValue; - nl_skb = cfg80211_vendor_cmd_alloc_reply_skb(sdev->wiphy, NLMSG_DEFAULT_SIZE); - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - ret = -ENOMEM; - goto exit_with_mib_resp; - } - - nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); - if (!nlattr_start) { - SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - ret = -EINVAL; - goto exit_with_mib_resp; - } - - ret = nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_BLACKLIST_SIZE, max_blacklist_size); - ret |= nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_WHITELIST_SIZE, max_whitelist_size); - if (ret) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", ret); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - goto exit_with_mib_resp; - } - - ret = cfg80211_vendor_cmd_reply(nl_skb); - if (ret) - SLSI_ERR(sdev, "cfg80211_vendor_cmd_reply failed :%d\n", ret); -exit_with_mib_resp: - kfree(mibrsp.data); - kfree(values); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return ret; -} - -static int slsi_set_roaming_state(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - int temp = 0; - int type = 0; - const struct nlattr *attr; - int ret = 0; - int roam_state = 0; - - if (!dev) { - SLSI_WARN_NODEV("net_dev is NULL\n"); - return -EINVAL; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_NL_ATTR_ROAM_STATE: - roam_state = nla_get_u8(attr); - break; - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_SET_ROAMING_STATE roam_state = %d\n", roam_state); - ret = slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ENABLED, roam_state); - if (ret < 0) - SLSI_ERR_NODEV("Failed to set roaming state\n"); - -exit: - return ret; -} - -char *slsi_get_roam_reason_str(int roam_reason) -{ - switch (roam_reason) { - case SLSI_WIFI_ROAMING_SEARCH_REASON_RESERVED: - return "WIFI_ROAMING_SEARCH_REASON_RESERVED"; - case SLSI_WIFI_ROAMING_SEARCH_REASON_LOW_RSSI: - return "WIFI_ROAMING_SEARCH_REASON_LOW_RSSI"; - case SLSI_WIFI_ROAMING_SEARCH_REASON_LINK_LOSS: - return "WIFI_ROAMING_SEARCH_REASON_LINK_LOSS"; - case SLSI_WIFI_ROAMING_SEARCH_REASON_BTM_REQ: - return "WIFI_ROAMING_SEARCH_REASON_BTM_REQ"; - case SLSI_WIFI_ROAMING_SEARCH_REASON_CU_TRIGGER: - return "WIFI_ROAMING_SEARCH_REASON_CU_TRIGGER"; - default: - return "UNKNOWN_REASON"; - } -} - -void slsi_rx_event_log_indication(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 event_id = 0; - u64 timestamp = 0; - u8 *tlv_data; - u32 roam_reason = 0, chan_utilisation = 0, btm_request_mode = 0, btm_response = 0, eapol_msg_type = 0; - u32 deauth_reason = 0, eapol_retry_count = 0, roam_rssi, status_code = 0; - u16 vendor_len, tag_id, tag_len, vtag_id, eapol_key_type = 0; - u32 tag_value, vtag_value, rssi_bits = 0; - int roam_rssi_val = 0; - __le16 *le16_ptr = NULL; - int tlv_buffer__len = fapi_get_datalen(skb), i = 0; - - SLSI_MUTEX_LOCK(sdev->logger_mutex); - event_id = fapi_get_s16(skb, u.mlme_event_log_ind.event); - timestamp = fapi_get_u64(skb, u.mlme_event_log_ind.timestamp); - tlv_data = fapi_get_data(skb); - - SLSI_DBG3(sdev, SLSI_GSCAN, - "slsi_rx_event_log_indication, event id = %d, len = %d\n", event_id, tlv_buffer__len); - -#ifdef CONFIG_SCSC_WIFILOGGER - SCSC_WLOG_FW_EVENT(WLOG_NORMAL, event_id, timestamp, fapi_get_data(skb), fapi_get_datalen(skb)); -#endif - while (i + 4 < tlv_buffer__len) { - le16_ptr = (__le16 *)&tlv_data[i]; - tag_id = le16_to_cpu(*le16_ptr); - le16_ptr = (__le16 *)&tlv_data[i + 2]; - tag_len = le16_to_cpu(*le16_ptr); - i += 4; - if (i + tag_len > tlv_buffer__len) { - SLSI_INFO(sdev, "Incorrect fapi bulk data\n"); - slsi_kfree_skb(skb); - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return; - } - tag_value = slsi_convert_tlv_data_to_value(&tlv_data[i], tag_len); - switch (tag_id) { - case SLSI_WIFI_TAG_RSSI: - roam_rssi = tag_value; - while (roam_rssi) { - rssi_bits++; - roam_rssi >>= 1; - } - roam_rssi_val = ((1 << rssi_bits) - 1) ^ tag_value; - roam_rssi_val = -(roam_rssi_val + 1); - break; - case SLSI_WIFI_TAG_REASON_CODE: - deauth_reason = tag_value; - break; - case SLSI_WIFI_TAG_VENDOR_SPECIFIC: - vendor_len = tag_len - 2; - le16_ptr = (__le16 *)&tlv_data[i]; - vtag_id = le16_to_cpu(*le16_ptr); - vtag_value = slsi_convert_tlv_data_to_value(&tlv_data[i + 2], vendor_len); - switch (vtag_id) { - case SLSI_WIFI_TAG_VD_CHANNEL_UTILISATION: - chan_utilisation = vtag_value; - break; - case SLSI_WIFI_TAG_VD_ROAMING_REASON: - roam_reason = vtag_value; - break; - case SLSI_WIFI_TAG_VD_BTM_REQUEST_MODE: - btm_request_mode = vtag_value; - break; - case SLSI_WIFI_TAG_VD_BTM_RESPONSE_STATUS: - btm_response = vtag_value; - break; - case SLSI_WIFI_TAG_VD_RETRY_COUNT: - eapol_retry_count = vtag_value; - break; - case SLSI_WIFI_TAG_VD_EAPOL_KEY_TYPE: - eapol_key_type = vtag_value; - break; - } - break; - case SLSI_WIFI_TAG_EAPOL_MESSAGE_TYPE: - eapol_msg_type = tag_value; - break; - case SLSI_WIFI_TAG_STATUS: - status_code = tag_value; - break; - } - i += tag_len; - } - switch (event_id) { - case FAPI_EVENT_WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START: - if (eapol_key_type == SLSI_WIFI_EAPOL_KEY_TYPE_GTK) - SLSI_INFO(sdev, "WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START, Send GTK, G%d\n", eapol_msg_type); - else if (eapol_key_type == SLSI_WIFI_EAPOL_KEY_TYPE_PTK) - SLSI_INFO(sdev, "WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START, Send 4way-H/S, M%d\n", - eapol_msg_type); - break; - case FAPI_EVENT_WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP: - SLSI_INFO(sdev, "WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP,Result Code:%d, Retry Count:%d\n", - status_code, eapol_retry_count); - break; - case FAPI_EVENT_WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED: - if (eapol_key_type == SLSI_WIFI_EAPOL_KEY_TYPE_GTK) - SLSI_INFO(sdev, "WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED, Received GTK, G%d\n", eapol_msg_type); - else if (eapol_key_type == SLSI_WIFI_EAPOL_KEY_TYPE_PTK) - SLSI_INFO(sdev, "WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED, Received 4way-H/S, M%d\n", eapol_msg_type); - break; - case WIFI_EVENT_FW_BTM_FRAME_REQUEST: - SLSI_INFO(sdev, "WIFI_EVENT_FW_BTM_FRAME_REQUEST,Request Mode:%d\n", btm_request_mode); - break; - case WIFI_EVENT_FW_BTM_FRAME_RESPONSE: - SLSI_INFO(sdev, "WIFI_EVENT_FW_BTM_FRAME_RESPONSE,Status code:%d\n", btm_response); - break; - case FAPI_EVENT_WIFI_EVENT_ROAM_SEARCH_STARTED: - SLSI_INFO(sdev, "WIFI_EVENT_ROAM_SEARCH_STARTED, RSSI:%d, Deauth Reason:0x%04x, Channel Utilisation:%d," - "Roam Reason: %s\n", roam_rssi_val, deauth_reason, chan_utilisation, - slsi_get_roam_reason_str(roam_reason)); - break; - case FAPI_EVENT_WIFI_EVENT_FW_AUTH_STARTED: - SLSI_INFO(sdev, "WIFI_EVENT_FW_AUTH_STARTED\n"); - break; - case FAPI_EVENT_WIFI_EVENT_AUTH_COMPLETE: - SLSI_INFO(sdev, "WIFI_EVENT_AUTH_COMPLETE,Status code:%d\n", status_code); - break; - case FAPI_EVENT_WIFI_EVENT_ROAM_ASSOC_COMPLETE: - SLSI_INFO(sdev, "Received Association Response\n"); - break; - case WIFI_EVENT_FW_NR_FRAME_REQUEST: - SLSI_INFO(sdev, "Send Radio Measurement Frame (Neighbor Report Req)\n"); - break; - case WIFI_EVENT_FW_RM_FRAME_RESPONSE: - SLSI_INFO(sdev, "Received Radio Measurement Frame (Radio Measurement Rep)\n"); - break; - } - - slsi_kfree_skb(skb); - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); -} - -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING -static void slsi_on_ring_buffer_data(char *ring_name, char *buffer, int buffer_size, - struct scsc_wifi_ring_buffer_status *buffer_status, void *ctx) -{ - struct sk_buff *skb; - int event_id = SLSI_NL80211_LOGGER_RING_EVENT; - struct slsi_dev *sdev = ctx; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, buffer_size, event_id, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, buffer_size, event_id, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for vendor event: %d\n", event_id); - return; - } - - if (nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_STATUS, sizeof(*buffer_status), buffer_status) || - nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_DATA, buffer_size, buffer)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - return; - } - cfg80211_vendor_event(skb, GFP_KERNEL); -} - -static void slsi_on_alert(char *buffer, int buffer_size, int err_code, void *ctx) -{ - struct sk_buff *skb; - int event_id = SLSI_NL80211_LOGGER_FW_DUMP_EVENT; - struct slsi_dev *sdev = ctx; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, buffer_size, event_id, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, buffer_size, event_id, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for vendor event: %d\n", event_id); - goto exit; - } - - if (nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_DUMP_LEN, buffer_size) || - nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_DATA, buffer_size, buffer)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - goto exit; - } - cfg80211_vendor_event(skb, GFP_KERNEL); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); -} - -static void slsi_on_firmware_memory_dump(char *buffer, int buffer_size, void *ctx) -{ - SLSI_ERR_NODEV("slsi_on_firmware_memory_dump\n"); - kfree(mem_dump_buffer); - mem_dump_buffer = NULL; - mem_dump_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!mem_dump_buffer) { - SLSI_ERR_NODEV("Failed to allocate memory for mem_dump_buffer\n"); - return; - } - mem_dump_buffer_size = buffer_size; - memcpy(mem_dump_buffer, buffer, mem_dump_buffer_size); -} - -static void slsi_on_driver_memory_dump(char *buffer, int buffer_size, void *ctx) -{ - SLSI_ERR_NODEV("slsi_on_driver_memory_dump\n"); - kfree(mem_dump_buffer); - mem_dump_buffer = NULL; - mem_dump_buffer_size = buffer_size; - mem_dump_buffer = kmalloc(mem_dump_buffer_size, GFP_KERNEL); - if (!mem_dump_buffer) { - SLSI_ERR_NODEV("Failed to allocate memory for mem_dump_buffer\n"); - return; - } - memcpy(mem_dump_buffer, buffer, mem_dump_buffer_size); -} - -static int slsi_enable_logging(struct slsi_dev *sdev, bool enable) -{ - int status = 0; -#ifdef ENABLE_WIFI_LOGGER_MIB_WRITE - struct slsi_mib_data mib_data = { 0, NULL }; - - SLSI_DBG3(sdev, SLSI_GSCAN, "Value of enable is : %d\n", enable); - status = slsi_mib_encode_bool(&mib_data, SLSI_PSID_UNIFI_LOGGER_ENABLED, enable, 0); - if (status != SLSI_MIB_STATUS_SUCCESS) { - SLSI_ERR(sdev, "slsi_enable_logging failed: no mem for MIB\n"); - status = -ENOMEM; - goto exit; - } - status = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - kfree(mib_data.data); - if (status) - SLSI_ERR(sdev, "Err setting unifiLoggerEnabled MIB. error = %d\n", status); - -exit: - return status; -#else - SLSI_DBG3(sdev, SLSI_GSCAN, "UnifiLoggerEnabled MIB write disabled\n"); - return status; -#endif -} - -static int slsi_start_logging(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp = 0; - int type = 0; - char ring_name[32] = {0}; - int verbose_level = 0; - int ring_flags = 0; - int max_interval_sec = 0; - int min_data_size = 0; - const struct nlattr *attr; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_NAME: - strncpy(ring_name, nla_data(attr), MIN(sizeof(ring_name) - 1, nla_len(attr))); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_VERBOSE_LEVEL: - verbose_level = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_FLAGS: - ring_flags = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_LOG_MAX_INTERVAL: - max_interval_sec = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_LOG_MIN_DATA_SIZE: - min_data_size = nla_get_u32(attr); - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - ret = scsc_wifi_set_log_handler(slsi_on_ring_buffer_data, sdev); - if (ret < 0) { - SLSI_ERR(sdev, "scsc_wifi_set_log_handler failed ret: %d\n", ret); - goto exit; - } - ret = scsc_wifi_set_alert_handler(slsi_on_alert, sdev); - if (ret < 0) { - SLSI_ERR(sdev, "Warning : scsc_wifi_set_alert_handler failed ret: %d\n", ret); - } - ret = slsi_enable_logging(sdev, 1); - if (ret < 0) { - SLSI_ERR(sdev, "slsi_enable_logging for enable = 1, failed ret: %d\n", ret); - goto exit_with_reset_alert_handler; - } - ret = scsc_wifi_start_logging(verbose_level, ring_flags, max_interval_sec, min_data_size, ring_name); - if (ret < 0) { - SLSI_ERR(sdev, "scsc_wifi_start_logging failed ret: %d\n", ret); - goto exit_with_disable_logging; - } else { - goto exit; - } -exit_with_disable_logging: - ret = slsi_enable_logging(sdev, 0); - if (ret < 0) - SLSI_ERR(sdev, "slsi_enable_logging for enable = 0, failed ret: %d\n", ret); -exit_with_reset_alert_handler: - ret = scsc_wifi_reset_alert_handler(); - if (ret < 0) - SLSI_ERR(sdev, "Warning : scsc_wifi_reset_alert_handler failed ret: %d\n", ret); - ret = scsc_wifi_reset_log_handler(); - if (ret < 0) - SLSI_ERR(sdev, "scsc_wifi_reset_log_handler failed ret: %d\n", ret); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_reset_logging(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - ret = slsi_enable_logging(sdev, 0); - if (ret < 0) - SLSI_ERR(sdev, "slsi_enable_logging for enable = 0, failed ret: %d\n", ret); - ret = scsc_wifi_reset_log_handler(); - if (ret < 0) - SLSI_ERR(sdev, "scsc_wifi_reset_log_handler failed ret: %d\n", ret); - ret = scsc_wifi_reset_alert_handler(); - if (ret < 0) - SLSI_ERR(sdev, "Warning : scsc_wifi_reset_alert_handler failed ret: %d\n", ret); - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_trigger_fw_mem_dump(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - struct sk_buff *skb = NULL; - int length = 100; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - - ret = scsc_wifi_get_firmware_memory_dump(slsi_on_firmware_memory_dump, sdev); - if (ret) { - SLSI_ERR(sdev, "scsc_wifi_get_firmware_memory_dump failed : %d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, length); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - if (nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_DUMP_LEN, mem_dump_buffer_size)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); - -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_fw_mem_dump(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp = 0; - int type = 0; - int buf_len = 0; - void __user *user_buf = NULL; - const struct nlattr *attr; - struct sk_buff *skb; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_DUMP_LEN: - buf_len = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_DUMP_DATA: - user_buf = (void __user *)(unsigned long)nla_get_u64(attr); - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return -EINVAL; - } - } - if (buf_len > 0 && user_buf) { - ret = copy_to_user(user_buf, mem_dump_buffer, buf_len); - if (ret) { - SLSI_ERR(sdev, "failed to copy memdump into user buffer : %d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 100); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - /* Indicate the memdump is successfully copied */ - if (nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_DUMP_DATA, sizeof(ret), &ret)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); - } - -exit: - kfree(mem_dump_buffer); - mem_dump_buffer = NULL; - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_trigger_driver_mem_dump(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - struct sk_buff *skb = NULL; - int length = 100; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - - ret = scsc_wifi_get_driver_memory_dump(slsi_on_driver_memory_dump, sdev); - if (ret) { - SLSI_ERR(sdev, "scsc_wifi_get_driver_memory_dump failed : %d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, length); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - if (nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_DUMP_LEN, mem_dump_buffer_size)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); - -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_driver_mem_dump(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp = 0; - int type = 0; - int buf_len = 0; - void __user *user_buf = NULL; - const struct nlattr *attr; - struct sk_buff *skb; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_DUMP_LEN: - buf_len = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_DUMP_DATA: - user_buf = (void __user *)(unsigned long)nla_get_u64(attr); - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return -EINVAL; - } - } - if (buf_len > 0 && user_buf) { - ret = copy_to_user(user_buf, mem_dump_buffer, buf_len); - if (ret) { - SLSI_ERR(sdev, "failed to copy memdump into user buffer : %d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 100); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - /* Indicate the memdump is successfully copied */ - if (nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_DUMP_DATA, sizeof(ret), &ret)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); - } - -exit: - kfree(mem_dump_buffer); - mem_dump_buffer = NULL; - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_version(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp = 0; - int type = 0; - int buffer_size = 1024; - bool log_version = false; - char *buffer; - const struct nlattr *attr; - - buffer = kzalloc(buffer_size, GFP_KERNEL); - if (!buffer) { - SLSI_ERR(sdev, "No mem. Size:%d\n", buffer_size); - return -ENOMEM; - } - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_VERSION: - log_version = true; - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_VERSION: - log_version = false; - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - if (log_version) - ret = scsc_wifi_get_driver_version(buffer, buffer_size); - else - ret = scsc_wifi_get_firmware_version(buffer, buffer_size); - - if (ret < 0) { - SLSI_ERR(sdev, "failed to get the version %d\n", ret); - goto exit; - } - - ret = slsi_vendor_cmd_reply(wiphy, buffer, strlen(buffer)); -exit: - kfree(buffer); - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_ring_buffers_status(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int num_rings = 10; - struct sk_buff *skb; - struct scsc_wifi_ring_buffer_status status[num_rings]; - - SLSI_DBG1(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - memset(status, 0, sizeof(struct scsc_wifi_ring_buffer_status) * num_rings); - ret = scsc_wifi_get_ring_buffers_status(&num_rings, status); - if (ret < 0) { - SLSI_ERR(sdev, "scsc_wifi_get_ring_buffers_status failed ret:%d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 700); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - /* Indicate that the ring count and ring buffers status is successfully copied */ - if (nla_put_u8(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_NUM, num_rings) || - nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_STATUS, sizeof(status[0]) * num_rings, status)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_ring_data(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp = 0; - int type = 0; - char ring_name[32] = {0}; - const struct nlattr *attr; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_NAME: - strncpy(ring_name, nla_data(attr), MIN(sizeof(ring_name) - 1, nla_len(attr))); - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - goto exit; - } - } - - ret = scsc_wifi_get_ring_data(ring_name); - if (ret < 0) - SLSI_ERR(sdev, "trigger_get_data failed ret:%d\n", ret); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_logger_supported_feature_set(struct wiphy *wiphy, struct wireless_dev *wdev, - const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - u32 supported_features = 0; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - ret = scsc_wifi_get_logger_supported_feature_set(&supported_features); - if (ret < 0) { - SLSI_ERR(sdev, "scsc_wifi_get_logger_supported_feature_set failed ret:%d\n", ret); - goto exit; - } - ret = slsi_vendor_cmd_reply(wiphy, &supported_features, sizeof(supported_features)); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_start_pkt_fate_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - int ret = 0; -#ifdef ENABLE_WIFI_LOGGER_MIB_WRITE - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct slsi_mib_data mib_data = { 0, NULL }; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - ret = slsi_mib_encode_bool(&mib_data, SLSI_PSID_UNIFI_TX_DATA_CONFIRM, 1, 0); - if (ret != SLSI_MIB_STATUS_SUCCESS) { - SLSI_ERR(sdev, "Failed to set UnifiTxDataConfirm MIB : no mem for MIB\n"); - ret = -ENOMEM; - goto exit; - } - - ret = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - - if (ret) { - SLSI_ERR(sdev, "Err setting UnifiTxDataConfirm MIB. error = %d\n", ret); - goto exit; - } - - ret = scsc_wifi_start_pkt_fate_monitoring(); - if (ret < 0) { - SLSI_ERR(sdev, "scsc_wifi_start_pkt_fate_monitoring failed, ret=%d\n", ret); - - // Resetting the SLSI_PSID_UNIFI_TX_DATA_CONFIRM mib back to 0. - mib_data.dataLength = 0; - mib_data.data = NULL; - ret = slsi_mib_encode_bool(&mib_data, SLSI_PSID_UNIFI_TX_DATA_CONFIRM, 1, 0); - if (ret != SLSI_MIB_STATUS_SUCCESS) { - SLSI_ERR(sdev, "Failed to set UnifiTxDataConfirm MIB : no mem for MIB\n"); - ret = -ENOMEM; - goto exit; - } - - ret = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength); - - if (ret) { - SLSI_ERR(sdev, "Err setting UnifiTxDataConfirm MIB. error = %d\n", ret); - goto exit; - } - } -exit: - kfree(mib_data.data); - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -#else - SLSI_ERR_NODEV("slsi_start_pkt_fate_monitoring : UnifiTxDataConfirm MIB write disabled\n"); - return ret; -#endif -} - -static int slsi_get_tx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp = 0; - int type = 0; - void __user *user_buf = NULL; - u32 req_count = 0; - size_t provided_count = 0; - struct sk_buff *skb; - const struct nlattr *attr; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_NUM: - req_count = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_DATA: - user_buf = (void __user *)(unsigned long)nla_get_u64(attr); - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - ret = scsc_wifi_get_tx_pkt_fates(user_buf, req_count, &provided_count); - if (ret < 0) { - SLSI_ERR(sdev, "scsc_wifi_get_tx_pkt_fates failed ret: %d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 200); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - if (nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_NUM, sizeof(provided_count), &provided_count)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_rx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - int ret = 0; - int temp = 0; - int type = 0; - void __user *user_buf = NULL; - u32 req_count = 0; - size_t provided_count = 0; - struct sk_buff *skb; - const struct nlattr *attr; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_NUM: - req_count = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_DATA: - user_buf = (void __user *)(unsigned long)nla_get_u64(attr); - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - ret = scsc_wifi_get_rx_pkt_fates(user_buf, req_count, &provided_count); - if (ret < 0) { - SLSI_ERR(sdev, "scsc_wifi_get_rx_pkt_fates failed ret: %d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 200); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - if (nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_NUM, sizeof(provided_count), &provided_count)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -static int slsi_get_wake_reason_stats(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct slsi_wlan_driver_wake_reason_cnt wake_reason_count; - int ret = 0; - int temp = 0; - int type = 0; - const struct nlattr *attr; - struct sk_buff *skb; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - // Initialising the wake_reason_count structure values to 0. - memset(&wake_reason_count, 0, sizeof(struct slsi_wlan_driver_wake_reason_cnt)); - - SLSI_MUTEX_LOCK(sdev->logger_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ: - wake_reason_count.cmd_event_wake_cnt_sz = nla_get_u32(attr); - break; - case SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ: - wake_reason_count.driver_fw_local_wake_cnt_sz = nla_get_u32(attr); - break; - default: - SLSI_ERR(sdev, "Unknown type: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - if (ret < 0) { - SLSI_ERR(sdev, "Failed to get wake reason stats : %d\n", ret); - goto exit; - } - - /* Alloc the SKB for vendor_event */ - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 700); - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for Vendor event\n"); - ret = -ENOMEM; - goto exit; - } - - if (nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE, - wake_reason_count.total_cmd_event_wake)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - if (nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR, 0, - wake_reason_count.cmd_event_wake_cnt)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - if (nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE, - wake_reason_count.total_driver_fw_local_wake)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - if (nla_put(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0, - wake_reason_count.driver_fw_local_wake_cnt)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - if (nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE, - wake_reason_count.total_rx_data_wake) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT, - wake_reason_count.rx_wake_details.rx_unicast_cnt) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT, - wake_reason_count.rx_wake_details.rx_multicast_cnt) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT, - wake_reason_count.rx_wake_details.rx_broadcast_cnt) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP_PKT, - wake_reason_count.rx_wake_pkt_classification_info.icmp_pkt) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_PKT, - wake_reason_count.rx_wake_pkt_classification_info.icmp6_pkt) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_RA, - wake_reason_count.rx_wake_pkt_classification_info.icmp6_ra) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_NA, - wake_reason_count.rx_wake_pkt_classification_info.icmp6_na) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_NS, - wake_reason_count.rx_wake_pkt_classification_info.icmp6_ns) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT, - wake_reason_count.rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT, - wake_reason_count.rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt) || - nla_put_u32(skb, SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT, - wake_reason_count.rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt)) { - SLSI_ERR_NODEV("Failed nla_put\n"); - slsi_kfree_skb(skb); - ret = -EINVAL; - goto exit; - } - ret = cfg80211_vendor_cmd_reply(skb); - - if (ret) - SLSI_ERR(sdev, "Vendor Command reply failed ret:%d\n", ret); -exit: - SLSI_MUTEX_UNLOCK(sdev->logger_mutex); - return ret; -} - -#endif /* CONFIG_SCSC_WLAN_ENHANCED_LOGGING */ - -static int slsi_acs_validate_width_hw_mode(struct slsi_acs_request *request) -{ - if (request->hw_mode != SLSI_ACS_MODE_IEEE80211A && request->hw_mode != SLSI_ACS_MODE_IEEE80211B && - request->hw_mode != SLSI_ACS_MODE_IEEE80211G) - return -EINVAL; - if (request->ch_width != 20 && request->ch_width != 40 && request->ch_width != 80) - return -EINVAL; - return 0; -} - -static int slsi_acs_init(struct wiphy *wiphy, - struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - struct netdev_vif *ndev_vif; - struct slsi_acs_request *request; - int temp; - int type; - const struct nlattr *attr; - int r = 0; - u32 *freq_list = NULL; - int freq_list_len = 0; - - SLSI_INFO(sdev, "SUBCMD_ACS_INIT Received\n"); - if (slsi_is_test_mode_enabled()) { - SLSI_ERR(sdev, "Not supported in WlanLite mode\n"); - return -EOPNOTSUPP; - } - if (wdev->iftype != NL80211_IFTYPE_AP) { - SLSI_ERR(sdev, "Invalid iftype: %d\n", wdev->iftype); - return -EINVAL; - } - if (!dev) { - SLSI_ERR(sdev, "Dev not found!\n"); - return -ENODEV; - } - request = kcalloc(1, sizeof(*request), GFP_KERNEL); - if (!request) { - SLSI_ERR(sdev, "No memory for request!"); - return -ENOMEM; - } - ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_ACS_ATTR_HW_MODE: - { - request->hw_mode = nla_get_u8(attr); - SLSI_INFO(sdev, "ACS hw mode: %d\n", request->hw_mode); - break; - } - case SLSI_ACS_ATTR_CHWIDTH: - { - request->ch_width = nla_get_u16(attr); - SLSI_INFO(sdev, "ACS ch_width: %d\n", request->ch_width); - break; - } - case SLSI_ACS_ATTR_FREQ_LIST: - { - if (freq_list) /* This check is to avoid Prevent Issue */ - break; - - freq_list = kmalloc(nla_len(attr), GFP_KERNEL); - if (!freq_list) { - SLSI_ERR(sdev, "No memory for frequency list!"); - kfree(request); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return -ENOMEM; - } - memcpy(freq_list, nla_data(attr), nla_len(attr)); - freq_list_len = nla_len(attr) / sizeof(u32); - SLSI_INFO(sdev, "ACS freq_list_len: %d\n", freq_list_len); - break; - } - default: - if (type > SLSI_ACS_ATTR_MAX) - SLSI_ERR(sdev, "Invalid type : %d\n", type); - break; - } - } - - r = slsi_acs_validate_width_hw_mode(request); - if (r == 0 && freq_list_len) { - struct ieee80211_channel *channels[freq_list_len]; - struct slsi_acs_chan_info ch_info[MAX_CHAN_VALUE_ACS]; - struct slsi_acs_selected_channels acs_selected_channels; - int i = 0, num_channels = 0; - int idx; - u32 chan_flags = (IEEE80211_CHAN_INDOOR_ONLY | IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_DISABLED | -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13) - IEEE80211_CHAN_PASSIVE_SCAN -#else - IEEE80211_CHAN_NO_IR -#endif - ); - - memset(channels, 0, sizeof(channels)); - memset(&ch_info, 0, sizeof(ch_info)); - for (i = 0; i < freq_list_len; i++) { - channels[num_channels] = ieee80211_get_channel(wiphy, freq_list[i]); - if (!channels[num_channels]) { - SLSI_INFO(sdev, "Ignore invalid freq:%d in freq list\n", freq_list[i]); - } else if (channels[num_channels]->flags & chan_flags) { - SLSI_INFO(sdev, "Skip invalid channel:%d for ACS\n", channels[num_channels]->hw_value); - } else { - idx = slsi_find_chan_idx(channels[num_channels]->hw_value, request->hw_mode); - ch_info[idx].chan = channels[num_channels]->hw_value; - num_channels++; - } - } - - if (num_channels == 1) { - memset(&acs_selected_channels, 0, sizeof(acs_selected_channels)); - acs_selected_channels.ch_width = 20; - acs_selected_channels.hw_mode = request->hw_mode; - acs_selected_channels.pri_channel = channels[0]->hw_value; - r = slsi_send_acs_event(sdev, acs_selected_channels); - sdev->acs_channel_switched = true; - kfree(freq_list); - kfree(request); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return r; - } - - if (request->hw_mode == SLSI_ACS_MODE_IEEE80211A) - request->ch_list_len = 25; - else - request->ch_list_len = 14; - memcpy(&request->acs_chan_info[0], &ch_info[0], sizeof(ch_info)); - ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request = request; - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = false; - r = slsi_mlme_add_scan(sdev, - dev, - FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION, - FAPI_REPORTMODE_REAL_TIME, - 0, /* n_ssids */ - NULL, /* ssids */ - num_channels, - channels, - NULL, - NULL, /* ie */ - 0, /* ie_len */ - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan); - } else { - SLSI_ERR(sdev, "Invalid freq_list len:%d or ch_width:%d or hw_mode:%d\n", freq_list_len, - request->ch_width, request->hw_mode); - r = -EINVAL; - kfree(request); - } - kfree(freq_list); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return r; -} - -static int slsi_configure_latency_mode(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - int temp = 0; - int type = 0; - const struct nlattr *attr; - int ret = 0; - int low_latency_mode = 0; - - if (!dev) { - SLSI_ERR(sdev, "dev is NULL!!\n"); - return -EINVAL; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_NL_ATTRIBUTE_LATENCY_MODE: - low_latency_mode = nla_get_u8(attr); - break; - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - ret = slsi_set_latency_mode(dev, low_latency_mode, len); - if (ret) - SLSI_ERR(sdev, "Error in setting low latency mode ret:%d\n", ret); -exit: - return ret; -} - -static const struct nl80211_vendor_cmd_info slsi_vendor_events[] = { - /**********Deprecated now due to fapi updates.Do not remove*/ - { OUI_GOOGLE, SLSI_NL80211_SIGNIFICANT_CHANGE_EVENT }, - { OUI_GOOGLE, SLSI_NL80211_HOTLIST_AP_FOUND_EVENT }, - /******************************************/ - { OUI_GOOGLE, SLSI_NL80211_SCAN_RESULTS_AVAILABLE_EVENT }, - { OUI_GOOGLE, SLSI_NL80211_FULL_SCAN_RESULT_EVENT }, - { OUI_GOOGLE, SLSI_NL80211_SCAN_EVENT }, - /**********Deprecated now due to fapi updates.Do not remove*/ - { OUI_GOOGLE, SLSI_NL80211_HOTLIST_AP_LOST_EVENT }, - /******************************************/ -#ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD - { OUI_SAMSUNG, SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH }, -#endif - { OUI_SAMSUNG, SLSI_NL80211_VENDOR_HANGED_EVENT }, - { OUI_GOOGLE, SLSI_NL80211_EPNO_EVENT }, - { OUI_GOOGLE, SLSI_NL80211_HOTSPOT_MATCH }, - { OUI_GOOGLE, SLSI_NL80211_RSSI_REPORT_EVENT}, -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING - { OUI_GOOGLE, SLSI_NL80211_LOGGER_RING_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_LOGGER_FW_DUMP_EVENT}, -#endif - { OUI_GOOGLE, SLSI_NL80211_NAN_RESPONSE_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_MATCH_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_FOLLOWUP_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_DISABLED_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_RTT_RESULT_EVENT}, - { OUI_GOOGLE, SLSI_NL80211_RTT_COMPLETE_EVENT}, - { OUI_SAMSUNG, SLSI_NL80211_VENDOR_ACS_EVENT}, - { OUI_SAMSUNG, SLSI_NL80211_VENDOR_FORWARD_BEACON}, - { OUI_SAMSUNG, SLSI_NL80211_VENDOR_FORWARD_BEACON_ABORT}, - { OUI_GOOGLE, SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS} -}; - -static const struct wiphy_vendor_command slsi_vendor_cmd[] = { - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_gscan_get_capabilities - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_gscan_get_valid_channel - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_gscan_add - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_gscan_del - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_gscan_get_scan_results - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_gscan_set_oui - }, -#ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD - { - { - .vendor_id = OUI_SAMSUNG, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_key_mgmt_set_pmk - }, -#endif - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_BLACKLIST - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_set_bssid_blacklist - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_START_KEEP_ALIVE_OFFLOAD - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_start_keepalive_offload - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_STOP_KEEP_ALIVE_OFFLOAD - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_stop_keepalive_offload - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_set_epno_ssid - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_set_hs_params - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_reset_hs_params - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_RSSI_MONITOR - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_set_rssi_monitor - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_LSTATS_SUBCMD_SET_STATS - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_lls_set_stats - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_LSTATS_SUBCMD_GET_STATS - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_lls_get_stats - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_LSTATS_SUBCMD_CLEAR_STATS - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_lls_clear_stats - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_FEATURE_SET - }, - .flags = 0, - .doit = slsi_get_feature_set - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_COUNTRY_CODE - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_set_country_code - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_CONFIGURE_ND_OFFLOAD - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_configure_nd_offload - }, -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_START_LOGGING - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_start_logging - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_RESET_LOGGING - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_reset_logging - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_TRIGGER_FW_MEM_DUMP - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_trigger_fw_mem_dump - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_FW_MEM_DUMP - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_fw_mem_dump - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_TRIGGER_DRIVER_MEM_DUMP - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_trigger_driver_mem_dump - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_DRIVER_MEM_DUMP - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_driver_mem_dump - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_VERSION - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_version - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_RING_STATUS - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_ring_buffers_status - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_RING_DATA - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_ring_data - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_FEATURE - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_logger_supported_feature_set - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_START_PKT_FATE_MONITORING - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_start_pkt_fate_monitoring - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_TX_PKT_FATES - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_tx_pkt_fates - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_RX_PKT_FATES - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_rx_pkt_fates - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_wake_reason_stats - }, -#endif /* CONFIG_SCSC_WLAN_ENHANCED_LOGGING */ -#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_ENABLE - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_enable - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_DISABLE - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_disable - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_PUBLISH - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_publish - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_PUBLISHCANCEL - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_publish_cancel - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_SUBSCRIBE - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_subscribe - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_SUBSCRIBECANCEL - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_subscribe_cancel - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_TXFOLLOWUP - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_transmit_followup - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_CONFIG - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_set_config - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_CAPABILITIES - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_nan_get_capabilities - }, -#endif - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_GET_ROAMING_CAPABILITIES - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_get_roaming_capabilities - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_ROAMING_STATE - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_set_roaming_state - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_RTT_GET_CAPABILITIES - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_rtt_get_capabilities - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_RTT_RANGE_START - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_rtt_set_config - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_RTT_RANGE_CANCEL - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_rtt_cancel_config - }, - { - { - .vendor_id = OUI_SAMSUNG, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_ACS_INIT - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_acs_init - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_APF_GET_CAPABILITIES - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_apf_get_capabilities - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_APF_SET_FILTER - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_apf_set_filter - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_APF_READ_FILTER - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_apf_read_filter - }, - { - { - .vendor_id = OUI_GOOGLE, - .subcmd = SLSI_NL80211_VENDOR_SUBCMD_SET_LATENCY_MODE - }, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, - .doit = slsi_configure_latency_mode - } -}; - -void slsi_nl80211_vendor_deinit(struct slsi_dev *sdev) -{ - SLSI_DBG2(sdev, SLSI_GSCAN, "De-initialise vendor command and events\n"); - sdev->wiphy->vendor_commands = NULL; - sdev->wiphy->n_vendor_commands = 0; - sdev->wiphy->vendor_events = NULL; - sdev->wiphy->n_vendor_events = 0; - - SLSI_DBG2(sdev, SLSI_GSCAN, "Gscan cleanup\n"); - slsi_gscan_flush_scan_results(sdev); - -} - -void slsi_nl80211_vendor_init(struct slsi_dev *sdev) -{ - int i; - - SLSI_DBG2(sdev, SLSI_GSCAN, "Init vendor command and events\n"); - - sdev->wiphy->vendor_commands = slsi_vendor_cmd; - sdev->wiphy->n_vendor_commands = ARRAY_SIZE(slsi_vendor_cmd); - sdev->wiphy->vendor_events = slsi_vendor_events; - sdev->wiphy->n_vendor_events = ARRAY_SIZE(slsi_vendor_events); - - for (i = 0; i < SLSI_GSCAN_MAX_BUCKETS; i++) - sdev->bucket[i].scan_id = (SLSI_GSCAN_SCAN_ID_START + i); - - for (i = 0; i < SLSI_GSCAN_HASH_TABLE_SIZE; i++) - sdev->gscan_hash_table[i] = NULL; - - INIT_LIST_HEAD(&sdev->hotlist_results); -} diff --git a/drivers/net/wireless/scsc/nl80211_vendor.h b/drivers/net/wireless/scsc/nl80211_vendor.h deleted file mode 100755 index 92269fe5f952..000000000000 --- a/drivers/net/wireless/scsc/nl80211_vendor.h +++ /dev/null @@ -1,1034 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "nl80211_vendor_nan.h" - -#ifndef __SLSI_NL80211_VENDOR_H_ -#define __SLSI_NL80211_VENDOR_H_ - -#define OUI_GOOGLE 0x001A11 -#define OUI_SAMSUNG 0x0000f0 -#define SLSI_NL80211_GSCAN_SUBCMD_RANGE_START 0x1000 -#define SLSI_NL80211_GSCAN_EVENT_RANGE_START 0x01 -#define SLSI_NL80211_LOGGING_SUBCMD_RANGE_START 0x1400 -#define SLSI_NL80211_NAN_SUBCMD_RANGE_START 0x1500 -#define SLSI_NL80211_RTT_SUBCMD_RANGE_START 0x1100 -#define SLSI_NL80211_APF_SUBCMD_RANGE_START 0x1600 -#define SLSI_GSCAN_SCAN_ID_START 0x410 -#define SLSI_GSCAN_SCAN_ID_END 0x500 - -#define SLSI_GSCAN_MAX_BUCKETS (8) -#define SLSI_GSCAN_MAX_CHANNELS (16) /* As per gscan.h */ -#define SLSI_GSCAN_MAX_HOTLIST_APS (64) -#define SLSI_GSCAN_MAX_BUCKETS_PER_GSCAN (SLSI_GSCAN_MAX_BUCKETS) -#define SLSI_GSCAN_MAX_SCAN_CACHE_SIZE (12000) -#define SLSI_GSCAN_MAX_AP_CACHE_PER_SCAN (16) -#define SLSI_GSCAN_MAX_SCAN_REPORTING_THRESHOLD (100) -#define SLSI_GSCAN_MAX_SIGNIFICANT_CHANGE_APS (64) -#define SLSI_GSCAN_MAX_EPNO_SSIDS (32) -#define SLSI_GSCAN_MAX_EPNO_HS2_PARAM (8) /* Framework is not using this. Tune when needed */ - -#define SLSI_REPORT_EVENTS_NONE (0) -#define SLSI_REPORT_EVENTS_EACH_SCAN (1) -#define SLSI_REPORT_EVENTS_FULL_RESULTS (2) -#define SLSI_REPORT_EVENTS_NO_BATCH (4) - -#define SLSI_NL_ATTRIBUTE_U32_LEN (NLA_HDRLEN + 4) -#define SLSI_NL_ATTRIBUTE_COUNTRY_CODE (4) -#define SLSI_NL_ATTRIBUTE_LATENCY_MODE (5) - -#define SLSI_NL_VENDOR_ID_OVERHEAD SLSI_NL_ATTRIBUTE_U32_LEN -#define SLSI_NL_VENDOR_SUBCMD_OVERHEAD SLSI_NL_ATTRIBUTE_U32_LEN -#define SLSI_NL_VENDOR_DATA_OVERHEAD (NLA_HDRLEN) - -#define SLSI_NL_VENDOR_REPLY_OVERHEAD (SLSI_NL_VENDOR_ID_OVERHEAD + \ - SLSI_NL_VENDOR_SUBCMD_OVERHEAD + \ - SLSI_NL_VENDOR_DATA_OVERHEAD) - -#define SLSI_GSCAN_RTT_UNSPECIFIED (-1) -#define SLSI_GSCAN_HASH_TABLE_SIZE (32) -#define SLSI_GSCAN_HASH_KEY_MASK (0x1F) -#define SLSI_GSCAN_GET_HASH_KEY(_key) (_key & SLSI_GSCAN_HASH_KEY_MASK) - -#define SLSI_KEEP_SCAN_RESULT (0) -#define SLSI_DISCARD_SCAN_RESULT (1) - -#define SLSI_GSCAN_MAX_BSSID_PER_IE (20) - -#define SLSI_LLS_CAPABILITY_QOS 0x00000001 /* set for QOS association */ -#define SLSI_LLS_CAPABILITY_PROTECTED 0x00000002 /* set for protected association (802.11 beacon frame control protected bit set)*/ -#define SLSI_LLS_CAPABILITY_INTERWORKING 0x00000004 /* set if 802.11 Extended Capabilities element interworking bit is set*/ -#define SLSI_LLS_CAPABILITY_HS20 0x00000008 /* set for HS20 association*/ -#define SLSI_LLS_CAPABILITY_SSID_UTF8 0x00000010 /* set is 802.11 Extended Capabilities element UTF-8 SSID bit is set*/ -#define SLSI_LLS_CAPABILITY_COUNTRY 0x00000020 /* set is 802.11 Country Element is present*/ - -#define TIMESPEC_TO_US(ts) (((u64)(ts).tv_sec * USEC_PER_SEC) + (ts).tv_nsec / NSEC_PER_USEC) - -/* Feature enums */ -#define SLSI_WIFI_HAL_FEATURE_INFRA 0x000001 /* Basic infrastructure mode */ -#define SLSI_WIFI_HAL_FEATURE_INFRA_5G 0x000002 /* Support for 5 GHz Band */ -#define SLSI_WIFI_HAL_FEATURE_HOTSPOT 0x000004 /* Support for GAS/ANQP */ -#define SLSI_WIFI_HAL_FEATURE_P2P 0x000008 /* Wifi-Direct */ -#define SLSI_WIFI_HAL_FEATURE_SOFT_AP 0x000010 /* Soft AP */ -#define SLSI_WIFI_HAL_FEATURE_GSCAN 0x000020 /* Google-Scan APIs */ -#define SLSI_WIFI_HAL_FEATURE_NAN 0x000040 /* Neighbor Awareness Networking */ -#define SLSI_WIFI_HAL_FEATURE_D2D_RTT 0x000080 /* Device-to-device RTT */ -#define SLSI_WIFI_HAL_FEATURE_D2AP_RTT 0x000100 /* Device-to-AP RTT */ -#define SLSI_WIFI_HAL_FEATURE_BATCH_SCAN 0x000200 /* Batched Scan (legacy) */ -#define SLSI_WIFI_HAL_FEATURE_PNO 0x000400 /* Preferred network offload */ -#define SLSI_WIFI_HAL_FEATURE_ADDITIONAL_STA 0x000800 /* Support for two STAs */ -#define SLSI_WIFI_HAL_FEATURE_TDLS 0x001000 /* Tunnel directed link setup */ -#define SLSI_WIFI_HAL_FEATURE_TDLS_OFFCHANNEL 0x002000 /* Support for TDLS off channel */ -#define SLSI_WIFI_HAL_FEATURE_EPR 0x004000 /* Enhanced power reporting */ -#define SLSI_WIFI_HAL_FEATURE_AP_STA 0x008000 /* Support for AP STA Concurrency */ -#define SLSI_WIFI_HAL_FEATURE_LINK_LAYER_STATS 0x010000 /* Link layer stats collection */ -#define SLSI_WIFI_HAL_FEATURE_LOGGER 0x020000 /* WiFi Logger */ -#define SLSI_WIFI_HAL_FEATURE_HAL_EPNO 0x040000 /* WiFi PNO enhanced */ -#define SLSI_WIFI_HAL_FEATURE_RSSI_MONITOR 0x080000 /* RSSI Monitor */ -#define SLSI_WIFI_HAL_FEATURE_MKEEP_ALIVE 0x100000 /* WiFi mkeep_alive */ -#define SLSI_WIFI_HAL_FEATURE_CONTROL_ROAMING 0x800000 /* Enable/Disable firmware roaming macro */ - -enum slsi_wifi_attr { - SLSI_NL_ATTRIBUTE_ND_OFFLOAD_VALUE = 0, - SLSI_NL_ATTRIBUTE_PNO_RANDOM_MAC_OUI -}; - -enum SLSI_APF_ATTRIBUTES { - SLSI_APF_ATTR_VERSION = 0, - SLSI_APF_ATTR_MAX_LEN, - SLSI_APF_ATTR_PROGRAM, - SLSI_APF_ATTR_PROGRAM_LEN -}; - -enum SLSI_ROAM_ATTRIBUTES { - SLSI_NL_ATTR_MAX_BLACKLIST_SIZE, - SLSI_NL_ATTR_MAX_WHITELIST_SIZE, - SLSI_NL_ATTR_ROAM_STATE -}; - -enum slsi_acs_attr_offload { - SLSI_ACS_ATTR_CHANNEL_INVALID = 0, - SLSI_ACS_ATTR_PRIMARY_CHANNEL, - SLSI_ACS_ATTR_SECONDARY_CHANNEL, - SLSI_ACS_ATTR_HW_MODE, - SLSI_ACS_ATTR_HT_ENABLED, - SLSI_ACS_ATTR_HT40_ENABLED, - SLSI_ACS_ATTR_VHT_ENABLED, - SLSI_ACS_ATTR_CHWIDTH, - SLSI_ACS_ATTR_CH_LIST, - SLSI_ACS_ATTR_VHT_SEG0_CENTER_CHANNEL, - SLSI_ACS_ATTR_VHT_SEG1_CENTER_CHANNEL, - SLSI_ACS_ATTR_FREQ_LIST, - /* keep last */ - SLSI_ACS_ATTR_AFTER_LAST, - SLSI_ACS_ATTR_MAX = - SLSI_ACS_ATTR_AFTER_LAST - 1 -}; - -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -enum slsi_wips_attr { - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_SSID = 0, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_BSSID, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_CHANNEL, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_BCN_INTERVAL, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_TIME_STAMP1, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_TIME_STAMP2, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_SYS_TIME, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_MAX -}; - -enum slsi_wips_abort_attr { - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_ABORT = 0, - SLSI_WLAN_VENDOR_ATTR_FORWARD_BEACON_ABORT_MAX, -}; - -enum slsi_forward_beacon_abort_reason { - SLSI_FORWARD_BEACON_ABORT_REASON_UNSPECIFIED = 0, - SLSI_FORWARD_BEACON_ABORT_REASON_SCANNING, - SLSI_FORWARD_BEACON_ABORT_REASON_ROAMING, - SLSI_FORWARD_BEACON_ABORT_REASON_SUSPENDED, - SLSI_FORWARD_BEACON_ABORT_REASON_OFFSET = 0x8007, -}; -#endif - -enum slsi_acs_hw_mode { - SLSI_ACS_MODE_IEEE80211B, - SLSI_ACS_MODE_IEEE80211G, - SLSI_ACS_MODE_IEEE80211A, - SLSI_ACS_MODE_IEEE80211AD, - SLSI_ACS_MODE_IEEE80211ANY, -}; - -enum GSCAN_ATTRIBUTE { - GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, - GSCAN_ATTRIBUTE_BASE_PERIOD, - GSCAN_ATTRIBUTE_BUCKETS_BAND, - GSCAN_ATTRIBUTE_BUCKET_ID, - GSCAN_ATTRIBUTE_BUCKET_PERIOD, - GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, - GSCAN_ATTRIBUTE_BUCKET_CHANNELS, - GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, - GSCAN_ATTRIBUTE_REPORT_THRESHOLD, - GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, - GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS, - GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, - - GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, - GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ - GSCAN_ATTRIBUTE_REPORT_EVENTS, - - /* remaining reserved for additional attributes */ - GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, - GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ - GSCAN_ATTRIBUTE_NUM_CHANNELS, - GSCAN_ATTRIBUTE_CHANNEL_LIST, - GSCAN_ATTRIBUTE_SCAN_ID, - GSCAN_ATTRIBUTE_SCAN_FLAGS, - GSCAN_ATTRIBUTE_SCAN_BUCKET_BIT, - - /* remaining reserved for additional attributes */ - GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, - GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, - GSCAN_ATTRIBUTE_MIN_BREACHING, - GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, - - GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 70, - GSCAN_ATTRIBUTE_BUCKET_EXPONENT, - GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, - - GSCAN_ATTRIBUTE_NUM_BSSID, - GSCAN_ATTRIBUTE_BLACKLIST_BSSID, - - GSCAN_ATTRIBUTE_MAX -}; - -enum epno_ssid_attribute { - SLSI_ATTRIBUTE_EPNO_MINIMUM_5G_RSSI, - SLSI_ATTRIBUTE_EPNO_MINIMUM_2G_RSSI, - SLSI_ATTRIBUTE_EPNO_INITIAL_SCORE_MAX, - SLSI_ATTRIBUTE_EPNO_CUR_CONN_BONUS, - SLSI_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS, - SLSI_ATTRIBUTE_EPNO_SECURE_BONUS, - SLSI_ATTRIBUTE_EPNO_5G_BONUS, - SLSI_ATTRIBUTE_EPNO_SSID_NUM, - SLSI_ATTRIBUTE_EPNO_SSID_LIST, - SLSI_ATTRIBUTE_EPNO_SSID, - SLSI_ATTRIBUTE_EPNO_SSID_LEN, - SLSI_ATTRIBUTE_EPNO_FLAGS, - SLSI_ATTRIBUTE_EPNO_AUTH, - SLSI_ATTRIBUTE_EPNO_MAX -}; - -enum epno_hs_attribute { - SLSI_ATTRIBUTE_EPNO_HS_PARAM_LIST, - SLSI_ATTRIBUTE_EPNO_HS_NUM, - SLSI_ATTRIBUTE_EPNO_HS_ID, - SLSI_ATTRIBUTE_EPNO_HS_REALM, - SLSI_ATTRIBUTE_EPNO_HS_CONSORTIUM_IDS, - SLSI_ATTRIBUTE_EPNO_HS_PLMN, - SLSI_ATTRIBUTE_EPNO_HS_MAX -}; - -enum gscan_bucket_attributes { - GSCAN_ATTRIBUTE_CH_BUCKET_1, - GSCAN_ATTRIBUTE_CH_BUCKET_2, - GSCAN_ATTRIBUTE_CH_BUCKET_3, - GSCAN_ATTRIBUTE_CH_BUCKET_4, - GSCAN_ATTRIBUTE_CH_BUCKET_5, - GSCAN_ATTRIBUTE_CH_BUCKET_6, - GSCAN_ATTRIBUTE_CH_BUCKET_7, - GSCAN_ATTRIBUTE_CH_BUCKET_8 -}; - -enum wifi_band { - WIFI_BAND_UNSPECIFIED, - WIFI_BAND_BG = 1, /* 2.4 GHz */ - WIFI_BAND_A = 2, /* 5 GHz without DFS */ - WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ - WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ - WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ - WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ -}; - -enum wifi_scan_event { - WIFI_SCAN_RESULTS_AVAILABLE, - WIFI_SCAN_THRESHOLD_NUM_SCANS, - WIFI_SCAN_THRESHOLD_PERCENT, - WIFI_SCAN_FAILED, -}; - -enum wifi_mkeep_alive_attribute { - MKEEP_ALIVE_ATTRIBUTE_ID, - MKEEP_ALIVE_ATTRIBUTE_IP_PKT, - MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, - MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, - MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, - MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC -}; - -enum wifi_rssi_monitor_attr { - SLSI_RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, - SLSI_RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, - SLSI_RSSI_MONITOR_ATTRIBUTE_START -}; - -enum lls_attribute { - LLS_ATTRIBUTE_SET_MPDU_SIZE_THRESHOLD = 1, - LLS_ATTRIBUTE_SET_AGGR_STATISTICS_GATHERING, - LLS_ATTRIBUTE_CLEAR_STOP_REQUEST_MASK, - LLS_ATTRIBUTE_CLEAR_STOP_REQUEST, - LLS_ATTRIBUTE_MAX -}; - -enum slsi_hal_vendor_subcmds { - SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES = SLSI_NL80211_GSCAN_SUBCMD_RANGE_START, - SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS, - SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN, - SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN, - SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS, - /*****Deprecated due to fapi updates.Do not remove.************/ - SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST, - SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST, - SLSI_NL80211_VENDOR_SUBCMD_GET_HOTLIST_RESULTS, - SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE, - SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE, - /********************************************************/ - SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, - SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS, - SLSI_NL80211_VENDOR_SUBCMD_START_KEEP_ALIVE_OFFLOAD, - SLSI_NL80211_VENDOR_SUBCMD_STOP_KEEP_ALIVE_OFFLOAD, - SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_BLACKLIST, - SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST, - SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST, - SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST, - SLSI_NL80211_VENDOR_SUBCMD_SET_RSSI_MONITOR, - SLSI_NL80211_VENDOR_SUBCMD_LSTATS_SUBCMD_SET_STATS, - SLSI_NL80211_VENDOR_SUBCMD_LSTATS_SUBCMD_GET_STATS, - SLSI_NL80211_VENDOR_SUBCMD_LSTATS_SUBCMD_CLEAR_STATS, - SLSI_NL80211_VENDOR_SUBCMD_GET_FEATURE_SET, - SLSI_NL80211_VENDOR_SUBCMD_SET_COUNTRY_CODE, - SLSI_NL80211_VENDOR_SUBCMD_CONFIGURE_ND_OFFLOAD, - SLSI_NL80211_VENDOR_SUBCMD_GET_ROAMING_CAPABILITIES, - SLSI_NL80211_VENDOR_SUBCMD_SET_ROAMING_STATE, - SLSI_NL80211_VENDOR_SUBCMD_SET_LATENCY_MODE, - SLSI_NL80211_VENDOR_SUBCMD_START_LOGGING = SLSI_NL80211_LOGGING_SUBCMD_RANGE_START, - SLSI_NL80211_VENDOR_SUBCMD_TRIGGER_FW_MEM_DUMP, - SLSI_NL80211_VENDOR_SUBCMD_GET_FW_MEM_DUMP, - SLSI_NL80211_VENDOR_SUBCMD_GET_VERSION, - SLSI_NL80211_VENDOR_SUBCMD_GET_RING_STATUS, - SLSI_NL80211_VENDOR_SUBCMD_GET_RING_DATA, - SLSI_NL80211_VENDOR_SUBCMD_GET_FEATURE, - SLSI_NL80211_VENDOR_SUBCMD_RESET_LOGGING, - SLSI_NL80211_VENDOR_SUBCMD_TRIGGER_DRIVER_MEM_DUMP, - SLSI_NL80211_VENDOR_SUBCMD_GET_DRIVER_MEM_DUMP, - SLSI_NL80211_VENDOR_SUBCMD_START_PKT_FATE_MONITORING, - SLSI_NL80211_VENDOR_SUBCMD_GET_TX_PKT_FATES, - SLSI_NL80211_VENDOR_SUBCMD_GET_RX_PKT_FATES, - SLSI_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS, - SLSI_NL80211_VENDOR_SUBCMD_NAN_ENABLE = SLSI_NL80211_NAN_SUBCMD_RANGE_START, - SLSI_NL80211_VENDOR_SUBCMD_NAN_DISABLE, - SLSI_NL80211_VENDOR_SUBCMD_NAN_PUBLISH, - SLSI_NL80211_VENDOR_SUBCMD_NAN_PUBLISHCANCEL, - SLSI_NL80211_VENDOR_SUBCMD_NAN_SUBSCRIBE, - SLSI_NL80211_VENDOR_SUBCMD_NAN_SUBSCRIBECANCEL, - SLSI_NL80211_VENDOR_SUBCMD_NAN_TXFOLLOWUP, - SLSI_NL80211_VENDOR_SUBCMD_NAN_CONFIG, - SLSI_NL80211_VENDOR_SUBCMD_NAN_CAPABILITIES, - SLSI_NL80211_VENDOR_SUBCMD_RTT_GET_CAPABILITIES = SLSI_NL80211_RTT_SUBCMD_RANGE_START, - SLSI_NL80211_VENDOR_SUBCMD_RTT_RANGE_START, - SLSI_NL80211_VENDOR_SUBCMD_RTT_RANGE_CANCEL, - SLSI_NL80211_VENDOR_SUBCMD_APF_SET_FILTER = SLSI_NL80211_APF_SUBCMD_RANGE_START, - SLSI_NL80211_VENDOR_SUBCMD_APF_GET_CAPABILITIES, - SLSI_NL80211_VENDOR_SUBCMD_APF_READ_FILTER -}; - -enum slsi_supp_vendor_subcmds { - SLSI_NL80211_VENDOR_SUBCMD_UNSPEC = 0, - SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY, - SLSI_NL80211_VENDOR_SUBCMD_ACS_INIT, -}; - -enum slsi_vendor_event_values { - /**********Deprecated now due to fapi updates.Do not remove*/ - SLSI_NL80211_SIGNIFICANT_CHANGE_EVENT, - SLSI_NL80211_HOTLIST_AP_FOUND_EVENT, - /******************************************/ - SLSI_NL80211_SCAN_RESULTS_AVAILABLE_EVENT, - SLSI_NL80211_FULL_SCAN_RESULT_EVENT, - SLSI_NL80211_SCAN_EVENT, - /**********Deprecated now due to fapi updates.Do not remove*/ - SLSI_NL80211_HOTLIST_AP_LOST_EVENT, - /******************************************/ - SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH, - SLSI_NL80211_VENDOR_HANGED_EVENT, - SLSI_NL80211_EPNO_EVENT, - SLSI_NL80211_HOTSPOT_MATCH, - SLSI_NL80211_RSSI_REPORT_EVENT, - SLSI_NL80211_LOGGER_RING_EVENT, - SLSI_NL80211_LOGGER_FW_DUMP_EVENT, - SLSI_NL80211_NAN_RESPONSE_EVENT, - SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT, - SLSI_NL80211_NAN_MATCH_EVENT, - SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT, - SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT, - SLSI_NL80211_NAN_FOLLOWUP_EVENT, - SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT, - SLSI_NL80211_NAN_DISABLED_EVENT, - SLSI_NL80211_RTT_RESULT_EVENT, - SLSI_NL80211_RTT_COMPLETE_EVENT, - SLSI_NL80211_VENDOR_ACS_EVENT, - SLSI_NL80211_VENDOR_FORWARD_BEACON, - SLSI_NL80211_VENDOR_FORWARD_BEACON_ABORT, - SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS, -}; - -enum slsi_lls_interface_mode { - SLSI_LLS_INTERFACE_STA = 0, - SLSI_LLS_INTERFACE_SOFTAP = 1, - SLSI_LLS_INTERFACE_IBSS = 2, - SLSI_LLS_INTERFACE_P2P_CLIENT = 3, - SLSI_LLS_INTERFACE_P2P_GO = 4, - SLSI_LLS_INTERFACE_NAN = 5, - SLSI_LLS_INTERFACE_MESH = 6, - SLSI_LLS_INTERFACE_UNKNOWN = -1 -}; - -enum slsi_lls_connection_state { - SLSI_LLS_DISCONNECTED = 0, - SLSI_LLS_AUTHENTICATING = 1, - SLSI_LLS_ASSOCIATING = 2, - SLSI_LLS_ASSOCIATED = 3, - SLSI_LLS_EAPOL_STARTED = 4, /* if done by firmware/driver*/ - SLSI_LLS_EAPOL_COMPLETED = 5, /* if done by firmware/driver*/ -}; - -enum slsi_lls_roam_state { - SLSI_LLS_ROAMING_IDLE = 0, - SLSI_LLS_ROAMING_ACTIVE = 1, -}; - -/* access categories */ -enum slsi_lls_traffic_ac { - SLSI_LLS_AC_VO = 0, - SLSI_LLS_AC_VI = 1, - SLSI_LLS_AC_BE = 2, - SLSI_LLS_AC_BK = 3, - SLSI_LLS_AC_MAX = 4, -}; - -/* channel operating width */ -enum slsi_lls_channel_width { - SLSI_LLS_CHAN_WIDTH_20 = 0, - SLSI_LLS_CHAN_WIDTH_40 = 1, - SLSI_LLS_CHAN_WIDTH_80 = 2, - SLSI_LLS_CHAN_WIDTH_160 = 3, - SLSI_LLS_CHAN_WIDTH_80P80 = 4, - SLSI_LLS_CHAN_WIDTH_5 = 5, - SLSI_LLS_CHAN_WIDTH_10 = 6, - SLSI_LLS_CHAN_WIDTH_INVALID = -1 -}; - -/* wifi peer type */ -enum slsi_lls_peer_type { - SLSI_LLS_PEER_STA, - SLSI_LLS_PEER_AP, - SLSI_LLS_PEER_P2P_GO, - SLSI_LLS_PEER_P2P_CLIENT, - SLSI_LLS_PEER_NAN, - SLSI_LLS_PEER_TDLS, - SLSI_LLS_PEER_INVALID, -}; - -/* slsi_enhanced_logging_attributes */ -enum slsi_enhanced_logging_attributes { - SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_VERSION, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_VERSION, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_ID, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_NAME, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_FLAGS, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_VERBOSE_LEVEL, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_LOG_MAX_INTERVAL, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_LOG_MIN_DATA_SIZE, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_DUMP_LEN, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_FW_DUMP_DATA, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_DATA, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_STATUS, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_RING_NUM, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_DUMP_LEN, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_DRIVER_DUMP_DATA, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_NUM, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_PKT_FATE_DATA, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_INVALID = 0, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP_PKT, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_PKT, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_RA, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_NA, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_NS, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT, - SLSI_ENHANCED_LOGGING_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT, -}; - -enum slsi_rtt_event_attributes { - SLSI_RTT_EVENT_ATTR_ADDR = 0, - SLSI_RTT_EVENT_ATTR_BURST_NUM, - SLSI_RTT_EVENT_ATTR_MEASUREMENT_NUM, - SLSI_RTT_EVENT_ATTR_SUCCESS_NUM, - SLSI_RTT_EVENT_ATTR_NUM_PER_BURST_PEER, - SLSI_RTT_EVENT_ATTR_STATUS, - SLSI_RTT_EVENT_ATTR_RETRY_AFTER_DURATION, - SLSI_RTT_EVENT_ATTR_TYPE, - SLSI_RTT_EVENT_ATTR_RSSI, - SLSI_RTT_EVENT_ATTR_RSSI_SPREAD, - SLSI_RTT_EVENT_ATTR_TX_PREAMBLE, - SLSI_RTT_EVENT_ATTR_TX_NSS, - SLSI_RTT_EVENT_ATTR_TX_BW, - SLSI_RTT_EVENT_ATTR_TX_MCS, - SLSI_RTT_EVENT_ATTR_TX_RATE, - SLSI_RTT_EVENT_ATTR_RX_PREAMBLE, - SLSI_RTT_EVENT_ATTR_RX_NSS, - SLSI_RTT_EVENT_ATTR_RX_BW, - SLSI_RTT_EVENT_ATTR_RX_MCS, - SLSI_RTT_EVENT_ATTR_RX_RATE, - SLSI_RTT_EVENT_ATTR_RTT, - SLSI_RTT_EVENT_ATTR_RTT_SD, - SLSI_RTT_EVENT_ATTR_RTT_SPREAD, - SLSI_RTT_EVENT_ATTR_DISTANCE_MM, - SLSI_RTT_EVENT_ATTR_DISTANCE_SD_MM, - SLSI_RTT_EVENT_ATTR_DISTANCE_SPREAD_MM, - SLSI_RTT_EVENT_ATTR_TIMESTAMP_US, - SLSI_RTT_EVENT_ATTR_BURST_DURATION_MSN, - SLSI_RTT_EVENT_ATTR_NEGOTIATED_BURST_NUM, - SLSI_RTT_EVENT_ATTR_LCI, - SLSI_RTT_EVENT_ATTR_LCR, - -}; - -/* RTT peer type */ -enum slsi_rtt_peer_type { - SLSI_RTT_PEER_AP = 0x1, - SLSI_RTT_PEER_STA, - SLSI_RTT_PEER_P2P_GO, - SLSI_RTT_PEER_P2P_CLIENT, - SLSI_RTT_PEER_NAN, -}; - -/* RTT Measurement Bandwidth */ -enum slsi_wifi_rtt_bw { - SLSI_WIFI_RTT_BW_5 = 0x01, - SLSI_WIFI_RTT_BW_10 = 0x02, - SLSI_WIFI_RTT_BW_20 = 0x04, - SLSI_WIFI_RTT_BW_40 = 0x08, - SLSI_WIFI_RTT_BW_80 = 0x10, - SLSI_WIFI_RTT_BW_160 = 0x20 -}; - -/* RTT Measurement Preamble */ -enum slsi_wifi_rtt_preamble { - SLSI_WIFI_RTT_PREAMBLE_LEGACY = 0x1, - SLSI_WIFI_RTT_PREAMBLE_HT = 0x2, - SLSI_WIFI_RTT_PREAMBLE_VHT = 0x4 -}; - -/* RTT Type */ -enum slsi_wifi_rtt_type { - SLSI_RTT_TYPE_1_SIDED = 0x1, - SLSI_RTT_TYPE_2_SIDED, -}; - -enum slsi_rtt_attribute { - SLSI_RTT_ATTRIBUTE_TARGET_CNT = 0, - SLSI_RTT_ATTRIBUTE_TARGET_INFO, - SLSI_RTT_ATTRIBUTE_TARGET_MAC, - SLSI_RTT_ATTRIBUTE_TARGET_TYPE, - SLSI_RTT_ATTRIBUTE_TARGET_PEER, - SLSI_RTT_ATTRIBUTE_TARGET_CHAN_FREQ, - SLSI_RTT_ATTRIBUTE_TARGET_PERIOD, - SLSI_RTT_ATTRIBUTE_TARGET_NUM_BURST, - SLSI_RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, - SLSI_RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, - SLSI_RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, - SLSI_RTT_ATTRIBUTE_TARGET_LCI, - SLSI_RTT_ATTRIBUTE_TARGET_LCR, - SLSI_RTT_ATTRIBUTE_TARGET_BURST_DURATION, - SLSI_RTT_ATTRIBUTE_TARGET_PREAMBLE, - SLSI_RTT_ATTRIBUTE_TARGET_BW, - SLSI_RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, - SLSI_RTT_ATTRIBUTE_RESULTS_PER_TARGET, - SLSI_RTT_ATTRIBUTE_RESULT_CNT, - SLSI_RTT_ATTRIBUTE_RESULT, - SLSI_RTT_ATTRIBUTE_TARGET_ID -}; - -/* Ranging status */ -enum slsi_wifi_rtt_status { - SLSI_RTT_STATUS_SUCCESS = 0, - SLSI_RTT_STATUS_FAILURE, /* general failure status */ - SLSI_RTT_STATUS_FAIL_NO_RSP, /* target STA does not respond to request */ - SLSI_RTT_STATUS_FAIL_REJECTED, /* request rejected. Applies to 2-sided RTT only*/ - SLSI_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, - SLSI_RTT_STATUS_FAIL_TM_TIMEOUT, /* timing measurement times out */ - SLSI_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, /* Target on different channel, cannot range */ - SLSI_RTT_STATUS_FAIL_NO_CAPABILITY, /* ranging not supported */ - SLSI_RTT_STATUS_ABORTED, /* request aborted for unknown reason */ - SLSI_RTT_STATUS_FAIL_INVALID_TS, /* Invalid T1-T4 timestamp */ - SLSI_RTT_STATUS_FAIL_PROTOCOL, /* 11mc protocol failed */ - SLSI_RTT_STATUS_FAIL_SCHEDULE, /* request could not be scheduled */ - SLSI_RTT_STATUS_FAIL_BUSY_TRY_LATER, /* responder cannot collaborate at time of request */ - SLSI_RTT_STATUS_INVALID_REQ, /* bad request args */ - SLSI_RTT_STATUS_NO_WIFI, /* WiFi not enabled */ - SLSI_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE /* Responder overrides param info, cannot range with new params */ -}; - -/* Format of information elements found in the beacon */ -struct slsi_wifi_information_element { - u8 id; /* element identifier */ - u8 len; /* number of bytes to follow */ - u8 data[]; -}; - -struct slsi_nl_gscan_capabilities { - int max_scan_cache_size; - int max_scan_buckets; - int max_ap_cache_per_scan; - int max_rssi_sample_size; - int max_scan_reporting_threshold; - int max_hotlist_aps; - int max_hotlist_ssids; - int max_significant_wifi_change_aps; - int max_bssid_history_entries; - int max_number_epno_networks; - int max_number_epno_networks_by_ssid; - int max_number_of_white_listed_ssid; -}; - -struct slsi_nl_channel_param { - int channel; - int dwell_time_ms; - int passive; /* 0 => active, 1 => passive scan; ignored for DFS */ -}; - -struct slsi_nl_bucket_param { - int bucket_index; - enum wifi_band band; - int period; /* desired period in millisecond */ - u8 report_events; - int max_period; /* If non-zero: scan period will grow exponentially to a maximum period of max_period */ - int exponent; /* multiplier: new_period = old_period ^ exponent */ - int step_count; /* number of scans performed at a given period and until the exponent is applied */ - int num_channels; - struct slsi_nl_channel_param channels[SLSI_GSCAN_MAX_CHANNELS]; -}; - -struct slsi_nl_gscan_param { - int base_period; /* base timer period in ms */ - int max_ap_per_scan; /* number of APs to store in each scan in the BSSID/RSSI history buffer */ - int report_threshold_percent; /* when scan_buffer is this much full, wake up application processor */ - int report_threshold_num_scans; /* wake up application processor after these many scans */ - int num_buckets; - struct slsi_nl_bucket_param nl_bucket[SLSI_GSCAN_MAX_BUCKETS]; -}; - -struct slsi_nl_scan_result_param { - u64 ts; /* time since boot (in microsecond) when the result was retrieved */ - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; /* NULL terminated */ - u8 bssid[6]; - int channel; /* channel frequency in MHz */ - int rssi; /* in db */ - s64 rtt; /* in nanoseconds */ - s64 rtt_sd; /* standard deviation in rtt */ - u16 beacon_period; /* period advertised in the beacon */ - u16 capability; /* capabilities advertised in the beacon */ - u32 ie_length; /* size of the ie_data blob */ - u8 ie_data[1]; /* beacon IE */ -}; - -struct slsi_bucket { - bool used; /* to identify if this entry is free */ - bool for_change_tracking; /* Indicates if this scan_id is used for change_tracking */ - u8 report_events; /* this is received from HAL/Framework */ - u16 scan_id; /* SLSI_GSCAN_SCAN_ID_START + */ - int scan_cycle; /* To find the current scan cycle */ - struct slsi_gscan *gscan; /* gscan ref in which this bucket belongs */ -}; - -struct slsi_gscan { - int max_ap_per_scan; /* received from HAL/Framework */ - int report_threshold_percent; /* received from HAL/Framework */ - int report_threshold_num_scans; /* received from HAL/Framework */ - int num_scans; - int num_buckets; /* received from HAL/Framework */ - struct slsi_nl_bucket_param nl_bucket; /* store the first bucket params. used in tracking*/ - struct slsi_bucket *bucket[SLSI_GSCAN_MAX_BUCKETS_PER_GSCAN]; - struct slsi_gscan *next; -}; - -struct slsi_gscan_param { - struct slsi_nl_bucket_param *nl_bucket; - struct slsi_bucket *bucket; -}; - -struct slsi_gscan_result { - struct slsi_gscan_result *hnext; - int scan_cycle; - int scan_res_len; - int anqp_length; - struct slsi_nl_scan_result_param nl_scan_res; -}; - -struct slsi_epno_ssid_param { - u16 flags; - u8 ssid_len; - u8 ssid[32]; -}; - -struct slsi_epno_param { - u16 min_5g_rssi; /* minimum 5GHz RSSI for a BSSID to be considered */ - u16 min_2g_rssi; /* minimum 2.4GHz RSSI for a BSSID to be considered */ - u16 initial_score_max; /* maximum score that a network can have before bonuses */ - u8 current_connection_bonus; /* report current connection bonus only, when there is a - * network's score this much higher than the current connection - */ - u8 same_network_bonus; /* score bonus for all networks with the same network flag */ - u8 secure_bonus; /* score bonus for networks that are not open */ - u8 band_5g_bonus; /* 5GHz RSSI score bonus (applied to all 5GHz networks) */ - u8 num_networks; /* number of wifi_epno_network objects */ - struct slsi_epno_ssid_param epno_ssid[]; /* PNO networks */ -}; - -struct slsi_epno_hs2_param { - u32 id; /* identifier of this network block, report this in event */ - u8 realm[256]; /* null terminated UTF8 encoded realm, 0 if unspecified */ - s64 roaming_consortium_ids[16]; /* roaming consortium ids to match, 0s if unspecified */ - u8 plmn[3]; /* mcc/mnc combination as per rules, 0s if unspecified */ -}; - -struct slsi_rssi_monitor_evt { - s16 rssi; - u8 bssid[ETH_ALEN]; -}; - -/* channel information */ -struct slsi_lls_channel_info { - enum slsi_lls_channel_width width; /* channel width (20, 40, 80, 80+80, 160)*/ - int center_freq; /* primary 20 MHz channel */ - int center_freq0; /* center frequency (MHz) first segment */ - int center_freq1; /* center frequency (MHz) second segment */ -}; - -/* channel statistics */ -struct slsi_lls_channel_stat { - struct slsi_lls_channel_info channel; - u32 on_time; /* msecs the radio is awake (32 bits number accruing over time) */ - u32 cca_busy_time; /* msecs the CCA register is busy (32 bits number accruing over time) */ -}; - -/* wifi rate */ -struct slsi_lls_rate { - u32 preamble :3; /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved*/ - u32 nss :2; /* 0:1x1, 1:2x2, 3:3x3, 4:4x4*/ - u32 bw :3; /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz*/ - u32 rate_mcs_idx :8; /* OFDM/CCK rate code mcs index*/ - u32 reserved :16; /* reserved*/ - u32 bitrate; /* units of 100 Kbps*/ -}; - -/* per rate statistics */ -struct slsi_lls_rate_stat { - struct slsi_lls_rate rate; /* rate information*/ - u32 tx_mpdu; /* number of successfully transmitted data pkts (ACK rcvd)*/ - u32 rx_mpdu; /* number of received data pkts*/ - u32 mpdu_lost; /* number of data packet losses (no ACK)*/ - u32 retries; /* total number of data pkt retries*/ - u32 retries_short; /* number of short data pkt retries*/ - u32 retries_long; /* number of long data pkt retries*/ -}; - -/* radio statistics */ -struct slsi_lls_radio_stat { - int radio; /* wifi radio (if multiple radio supported)*/ - u32 on_time; /* msecs the radio is awake (32 bits number accruing over time)*/ - u32 tx_time; /* msecs the radio is transmitting (32 bits number accruing over time)*/ - u32 rx_time; /* msecs the radio is in active receive (32 bits number accruing over time)*/ - u32 on_time_scan; /* msecs the radio is awake due to all scan (32 bits number accruing over time)*/ - u32 on_time_nbd; /* msecs the radio is awake due to NAN (32 bits number accruing over time)*/ - u32 on_time_gscan; /* msecs the radio is awake due to G?scan (32 bits number accruing over time)*/ - u32 on_time_roam_scan; /* msecs the radio is awake due to roam?scan (32 bits number accruing over time)*/ - u32 on_time_pno_scan; /* msecs the radio is awake due to PNO scan (32 bits number accruing over time)*/ - u32 on_time_hs20; /* msecs the radio is awake due to HS2.0 scans and GAS exchange (32 bits number accruing over time)*/ - u32 num_channels; /* number of channels*/ - struct slsi_lls_channel_stat channels[]; /* channel statistics*/ -}; - -struct slsi_lls_interface_link_layer_info { - enum slsi_lls_interface_mode mode; /* interface mode*/ - u8 mac_addr[6]; /* interface mac address (self)*/ - enum slsi_lls_connection_state state; /* connection state (valid for STA, CLI only)*/ - enum slsi_lls_roam_state roaming; /* roaming state*/ - u32 capabilities; /* WIFI_CAPABILITY_XXX (self)*/ - u8 ssid[33]; /* null terminated SSID*/ - u8 bssid[6]; /* bssid*/ - u8 ap_country_str[3]; /* country string advertised by AP*/ - u8 country_str[3]; /* country string for this association*/ -}; - -/* per peer statistics */ -struct slsi_lls_peer_info { - enum slsi_lls_peer_type type; /* peer type (AP, TDLS, GO etc.)*/ - u8 peer_mac_address[6]; /* mac address*/ - u32 capabilities; /* peer WIFI_CAPABILITY_XXX*/ - u32 num_rate; /* number of rates*/ - struct slsi_lls_rate_stat rate_stats[]; /* per rate statistics, number of entries = num_rate*/ -}; - -/* Per access category statistics */ -struct slsi_lls_wmm_ac_stat { - enum slsi_lls_traffic_ac ac; /* access category (VI, VO, BE, BK)*/ - u32 tx_mpdu; /* number of successfully transmitted unicast data pkts (ACK rcvd)*/ - u32 rx_mpdu; /* number of received unicast data packets*/ - u32 tx_mcast; /* number of successfully transmitted multicast data packets*/ - u32 rx_mcast; /* number of received multicast data packets*/ - u32 rx_ampdu; /* number of received unicast a-mpdus; support of this counter is optional*/ - u32 tx_ampdu; /* number of transmitted unicast a-mpdus; support of this counter is optional*/ - u32 mpdu_lost; /* number of data pkt losses (no ACK)*/ - u32 retries; /* total number of data pkt retries*/ - u32 retries_short; /* number of short data pkt retries*/ - u32 retries_long; /* number of long data pkt retries*/ - u32 contention_time_min; /* data pkt min contention time (usecs)*/ - u32 contention_time_max; /* data pkt max contention time (usecs)*/ - u32 contention_time_avg; /* data pkt avg contention time (usecs)*/ - u32 contention_num_samples; /* num of data pkts used for contention statistics*/ -}; - -struct slsi_rx_data_cnt_details { - int rx_unicast_cnt; /*Total rx unicast packet which woke up host */ - int rx_multicast_cnt; /*Total rx multicast packet which woke up host */ - int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */ -}; - -struct slsi_rx_wake_pkt_type_classification { - int icmp_pkt; /*wake icmp packet count */ - int icmp6_pkt; /*wake icmp6 packet count */ - int icmp6_ra; /*wake icmp6 RA packet count */ - int icmp6_na; /*wake icmp6 NA packet count */ - int icmp6_ns; /*wake icmp6 NS packet count */ -}; - -struct slsi_rx_multicast_cnt { - int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */ - int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */ - int other_rx_multicast_addr_cnt;/*Rx wake packet was non-ipv4 and non-ipv6*/ -}; - -/* - * Structure holding all the driver/firmware wake count reasons. - * - * Buffers for the array fields (cmd_event_wake_cnt/driver_fw_local_wake_cnt) - * are allocated and freed by the framework. The size of each allocated - * array is indicated by the corresponding |_cnt| field. HAL needs to fill in - * the corresponding |_used| field to indicate the number of elements used in - * the array. - */ -struct slsi_wlan_driver_wake_reason_cnt { - int total_cmd_event_wake; /* Total count of cmd event wakes */ - int *cmd_event_wake_cnt; /* Individual wake count array, each index a reason */ - int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */ - int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */ - - int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */ - int *driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */ - int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */ - int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the driver */ - - int total_rx_data_wake; /* total data rx packets, that woke up host */ - struct slsi_rx_data_cnt_details rx_wake_details; - struct slsi_rx_wake_pkt_type_classification rx_wake_pkt_classification_info; - struct slsi_rx_multicast_cnt rx_multicast_wake_pkt_info; -}; - -/* interface statistics */ -struct slsi_lls_iface_stat { - void *iface; /* wifi interface*/ - struct slsi_lls_interface_link_layer_info info; /* current state of the interface*/ - u32 beacon_rx; /* access point beacon received count from connected AP*/ - u64 average_tsf_offset; /* average beacon offset encountered (beacon_TSF - TBTT)*/ - u32 leaky_ap_detected; /* indicate that this AP typically leaks packets beyond the driver guard time.*/ - u32 leaky_ap_avg_num_frames_leaked; /* average number of frame leaked by AP after frame with PM bit set was ACK'ed by AP*/ - u32 leaky_ap_guard_time; - u32 mgmt_rx; /* access point mgmt frames received count from connected AP (including Beacon)*/ - u32 mgmt_action_rx; /* action frames received count*/ - u32 mgmt_action_tx; /* action frames transmit count*/ - int rssi_mgmt; /* access Point Beacon and Management frames RSSI (averaged)*/ - int rssi_data; /* access Point Data Frames RSSI (averaged) from connected AP*/ - int rssi_ack; /* access Point ACK RSSI (averaged) from connected AP*/ - struct slsi_lls_wmm_ac_stat ac[SLSI_LLS_AC_MAX]; /* per ac data packet statistics*/ - u32 num_peers; /* number of peers*/ - struct slsi_lls_peer_info peer_info[]; /* per peer statistics*/ -}; - -enum slsi_wifi_hal_api_return_types { - WIFI_HAL_SUCCESS = 0, - WIFI_HAL_ERROR_NONE = 0, - WIFI_HAL_ERROR_UNKNOWN = -1, - WIFI_HAL_ERROR_UNINITIALIZED = -2, - WIFI_HAL_ERROR_NOT_SUPPORTED = -3, - WIFI_HAL_ERROR_NOT_AVAILABLE = -4, - WIFI_HAL_ERROR_INVALID_ARGS = -5, - WIFI_HAL_ERROR_INVALID_REQUEST_ID = -6, - WIFI_HAL_ERROR_TIMED_OUT = -7, - WIFI_HAL_ERROR_TOO_MANY_REQUESTS = -8, - WIFI_HAL_ERROR_OUT_OF_MEMORY = -9 -}; - -struct slsi_rtt_capabilities { - u8 rtt_one_sided_supported; /* if 1-sided rtt data collection is supported */ - u8 rtt_ftm_supported; /* if ftm rtt data collection is supported */ - u8 lci_support; /* if initiator supports LCI request. Applies to 2-sided RTT */ - u8 lcr_support; /* if initiator supports LCR request. Applies to 2-sided RTT */ - u8 preamble_support; /* bit mask indicates what preamble is supported by initiator */ - u8 bw_support; /* bit mask indicates what BW is supported by initiator */ - u8 responder_supported; /* if 11mc responder mode is supported */ - u8 mc_version; /* draft 11mc spec version supported by chip. For instance, - *version 4.0 should be 40 and version 4.3 should be 43 etc. - */ -}; - -/* RTT configuration */ -struct slsi_rtt_config { - u8 peer_addr[ETH_ALEN]; /* peer device mac address */ - u16 type; /* 1-sided or 2-sided RTT */ - u16 channel_freq; /* Required for STA-AP mode, optional for P2P, NBD etc. */ - u16 channel_info; - u8 burst_period; /* Time interval between bursts (units: 100 ms). */ - /* Applies to 1-sided and 2-sided RTT multi-burst requests. - *Range: 0-31, 0: no preference by initiator (2-sided RTT) - */ - u8 num_burst; /* Total number of RTT bursts to be executed. It will be - *specified in the same way as the parameter "Number of - *Burst Exponent" found in the FTM frame format. It - *applies to both: 1-sided RTT and 2-sided RTT. Valid - *values are 0 to 15 as defined in 802.11mc std - *0 means single shot - *The implication of this parameter on the maximum - *number of RTT results is the following: - *for 1-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst) - *for 2-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst - 1) - */ - u8 num_frames_per_burst; /* num of frames per burst. - *Minimum value = 1, Maximum value = 31 - *For 2-sided this equals the number of FTM frames - *to be attempted in a single burst. This also - *equals the number of FTM frames that the - *initiator will request that the responder send - *in a single frame. - */ - u8 num_retries_per_ftmr; /* Maximum number of retries that the initiator can - *retry an FTMR frame. - *Minimum value = 0, Maximum value = 3 - */ - u8 burst_duration; /* Applies to 1-sided and 2-sided RTT. Valid values will - *be 2-11 and 15 as specified by the 802.11mc std for - *the FTM parameter burst duration. In a multi-burst - *request, if responder overrides with larger value, - *the initiator will return failure. In a single-burst - *request if responder overrides with larger value, - *the initiator will sent TMR_STOP to terminate RTT - *at the end of the burst_duration it requested. - */ - u16 preamble; /* RTT preamble to be used in the RTT frames */ - u16 bw; /* RTT BW to be used in the RTT frames */ - u16 LCI_request; /* 1: request LCI, 0: do not request LCI */ - u16 LCR_request; /* 1: request LCR, 0: do not request LCR */ -}; - -#define MAX_CHAN_VALUE_ACS 25 /*Max number of supported channel is 25*/ - -struct slsi_acs_chan_info { - u16 chan; - u8 num_ap; - u8 num_bss_load_ap; - u8 total_chan_utilization; - u8 avg_chan_utilization; - int rssi_factor; - int adj_rssi_factor; -}; - -struct slsi_acs_selected_channels { - u8 pri_channel; - u8 sec_channel; - u8 vht_seg0_center_ch; - u8 vht_seg1_center_ch; - u16 ch_width; - enum slsi_acs_hw_mode hw_mode; -}; - -struct slsi_acs_request { - struct slsi_acs_chan_info acs_chan_info[MAX_CHAN_VALUE_ACS]; - u8 hw_mode; - u16 ch_width; - u8 ch_list_len; -}; - -void slsi_nl80211_vendor_init(struct slsi_dev *sdev); -void slsi_nl80211_vendor_deinit(struct slsi_dev *sdev); -u8 slsi_gscan_get_scan_policy(enum wifi_band band); -void slsi_gscan_handle_scan_result(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 scan_id, bool scan_done); -void slsi_gscan_hash_remove(struct slsi_dev *sdev, u8 *mac); -void slsi_rx_significant_change_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -int slsi_gscan_alloc_buckets(struct slsi_dev *sdev, struct slsi_gscan *gscan, int num_buckets); -int slsi_vendor_event(struct slsi_dev *sdev, int event_id, const void *data, int len); -int slsi_mib_get_gscan_cap(struct slsi_dev *sdev, struct slsi_nl_gscan_capabilities *cap); -void slsi_rx_rssi_report_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -int slsi_mib_get_apf_cap(struct slsi_dev *sdev, struct net_device *dev); -int slsi_mib_get_rtt_cap(struct slsi_dev *sdev, struct net_device *dev, struct slsi_rtt_capabilities *cap); -int slsi_mlme_add_range_req(struct slsi_dev *sdev, u8 count, struct slsi_rtt_config *nl_rtt_params, - u16 rtt_id, u16 vif_idx, u8 *source_addr); -int slsi_mlme_del_range_req(struct slsi_dev *sdev, struct net_device *dev, u16 count, u8 *addr, u16 rtt_id); -void slsi_rx_range_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_range_done_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -int slsi_tx_rate_calc(struct sk_buff *nl_skb, u16 fw_rate, int res, bool tx_rate); -void slsi_check_num_radios(struct slsi_dev *sdev); -void slsi_rx_event_log_indication(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -#ifdef CONFIG_SCSC_WLAN_DEBUG -char *slsi_print_event_name(int event_id); -#endif - - -static inline bool slsi_is_gscan_id(u16 scan_id) -{ - if ((scan_id >= SLSI_GSCAN_SCAN_ID_START) && (scan_id <= SLSI_GSCAN_SCAN_ID_END)) - return true; - - return false; -} - -static inline enum slsi_lls_traffic_ac slsi_fapi_to_android_traffic_q(enum slsi_traffic_q fapi_q) -{ - switch (fapi_q) { - case SLSI_TRAFFIC_Q_BE: - return SLSI_LLS_AC_BE; - case SLSI_TRAFFIC_Q_BK: - return SLSI_LLS_AC_BK; - case SLSI_TRAFFIC_Q_VI: - return SLSI_LLS_AC_VI; - case SLSI_TRAFFIC_Q_VO: - return SLSI_LLS_AC_VO; - default: - return SLSI_LLS_AC_MAX; - } -} - -#endif diff --git a/drivers/net/wireless/scsc/nl80211_vendor_nan.c b/drivers/net/wireless/scsc/nl80211_vendor_nan.c deleted file mode 100755 index cf538980a0da..000000000000 --- a/drivers/net/wireless/scsc/nl80211_vendor_nan.c +++ /dev/null @@ -1,1786 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "cfg80211_ops.h" -#include "debug.h" -#include "mgt.h" -#include "mlme.h" - -struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev) -{ -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - return slsi_get_netdev(sdev, SLSI_NET_INDEX_NAN); -#else - return NULL; -#endif -} - -static int slsi_nan_get_new_id(u32 id_map, int max_ids) -{ - int i; - - for (i = 1; i <= max_ids; i++) { - if (!(id_map & BIT(i))) - return i; - } - return 0; -} - -static int slsi_nan_get_new_publish_id(struct netdev_vif *ndev_vif) -{ - return slsi_nan_get_new_id(ndev_vif->nan.publish_id_map, SLSI_NAN_MAX_PUBLISH_ID); -} - -static int slsi_nan_get_new_subscribe_id(struct netdev_vif *ndev_vif) -{ - return slsi_nan_get_new_id(ndev_vif->nan.subscribe_id_map, SLSI_NAN_MAX_SUBSCRIBE_ID); -} - -static bool slsi_nan_is_publish_id_active(struct netdev_vif *ndev_vif, u32 id) -{ - return ndev_vif->nan.publish_id_map & BIT(id); -} - -static bool slsi_nan_is_subscribe_id_active(struct netdev_vif *ndev_vif, u32 id) -{ - return ndev_vif->nan.subscribe_id_map & BIT(id); -} - -void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr) -{ - memset(nan_mac_addr, 0, ETH_ALEN); -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - if (slsi_dev_nan_supported(sdev)) - ether_addr_copy(nan_mac_addr, sdev->netdev_addresses[SLSI_NET_INDEX_NAN]); -#endif -} - -static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 error, u32 response_type, - u16 publish_subscribe_id, struct slsi_hal_nan_capabilities *capabilities) -{ - int reply_len; - struct sk_buff *reply; - - reply_len = SLSI_NL_VENDOR_REPLY_OVERHEAD + SLSI_NL_ATTRIBUTE_U32_LEN * - (3 + sizeof(struct slsi_hal_nan_capabilities)); - reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len); - if (!reply) { - SLSI_WARN_NODEV("SKB alloc failed for vendor_cmd reply\n"); - return; - } - - nla_put_u32(reply, NAN_REPLY_ATTR_STATUS_TYPE, status); - nla_put_u32(reply, NAN_REPLY_ATTR_VALUE, error); - nla_put_u32(reply, NAN_REPLY_ATTR_RESPONSE_TYPE, response_type); - - if (capabilities) { - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER, - capabilities->max_concurrent_nan_clusters); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, capabilities->max_publishes); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, capabilities->max_subscribes); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, capabilities->max_service_name_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, capabilities->max_match_filter_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN, - capabilities->max_total_match_filter_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN, - capabilities->max_service_specific_info_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, capabilities->max_vsa_data_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, capabilities->max_mesh_data_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, capabilities->max_ndi_interfaces); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, capabilities->max_ndp_sessions); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN, capabilities->max_app_info_len); - } else if (publish_subscribe_id) { - nla_put_u16(reply, NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, publish_subscribe_id); - } - - if (cfg80211_vendor_cmd_reply(reply)) - SLSI_ERR_NODEV("FAILED to reply nan coammnd. response_type:%d\n", response_type); -} - -static int slsi_nan_get_sdea_params_nl(struct slsi_dev *sdev, struct slsi_nan_sdea_ctrl_params *sdea_params, - const struct nlattr *iter, int nl_attr_id) -{ - switch (nl_attr_id) { - case NAN_REQ_ATTR_SDEA_PARAM_NDP_TYPE: - sdea_params->ndp_type = nla_get_u8(iter); - sdea_params->config_nan_data_path = 1; - break; - case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG: - sdea_params->security_cfg = nla_get_u8(iter); - sdea_params->config_nan_data_path = 1; - break; - case NAN_REQ_ATTR_SDEA_PARAM_RANGING_STATE: - sdea_params->ranging_state = nla_get_u8(iter); - sdea_params->config_nan_data_path = 1; - break; - case NAN_REQ_ATTR_SDEA_PARAM_RANGE_REPORT: - sdea_params->range_report = nla_get_u8(iter); - sdea_params->config_nan_data_path = 1; - break; - case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG: - sdea_params->qos_cfg = nla_get_u8(iter); - sdea_params->config_nan_data_path = 1; - break; - default: - return -EINVAL; - } - return 0; -} - -static int slsi_nan_get_ranging_cfg_nl(struct slsi_dev *sdev, struct slsi_nan_ranging_cfg *ranging_cfg, - const struct nlattr *iter, int nl_attr_id) -{ - switch (nl_attr_id) { - case NAN_REQ_ATTR_RANGING_CFG_INTERVAL: - ranging_cfg->ranging_interval_msec = nla_get_u32(iter); - break; - case NAN_REQ_ATTR_RANGING_CFG_INDICATION: - ranging_cfg->config_ranging_indications = nla_get_u32(iter); - break; - case NAN_REQ_ATTR_RANGING_CFG_INGRESS_MM: - ranging_cfg->distance_ingress_mm = nla_get_u32(iter); - break; - case NAN_REQ_ATTR_RANGING_CFG_EGRESS_MM: - ranging_cfg->distance_egress_mm = nla_get_u32(iter); - break; - default: - return -EINVAL; - } - return 0; -} - -static int slsi_nan_get_security_info_nl(struct slsi_dev *sdev, struct slsi_nan_security_info *sec_info, - const struct nlattr *iter, int nl_attr_id) -{ - u32 len = 0; - - switch (nl_attr_id) { - case NAN_REQ_ATTR_CIPHER_TYPE: - sec_info->cipher_type = nla_get_u32(iter); - break; - case NAN_REQ_ATTR_SECURITY_KEY_TYPE: - sec_info->key_info.key_type = nla_get_u8(iter); - break; - case NAN_REQ_ATTR_SECURITY_PMK_LEN: - len = nla_get_u32(iter); - sec_info->key_info.body.pmk_info.pmk_len = len; - break; - case NAN_REQ_ATTR_SECURITY_PMK: - memcpy(sec_info->key_info.body.pmk_info.pmk, nla_data(iter), len); - break; - case NAN_REQ_ATTR_SECURITY_PASSPHRASE_LEN: - len = nla_get_u32(iter); - sec_info->key_info.body.passphrase_info.passphrase_len = len; - break; - case NAN_REQ_ATTR_SECURITY_PASSPHRASE: - memcpy(sec_info->key_info.body.passphrase_info.passphrase, nla_data(iter), len); - break; - case NAN_REQ_ATTR_SCID_LEN: - sec_info->scid_len = nla_get_u32(iter); - break; - case NAN_REQ_ATTR_SCID: - memcpy(sec_info->scid, nla_data(iter), sec_info->scid_len); - break; - default: - return -EINVAL; - } - return 0; -} - -static int slsi_nan_get_range_resp_cfg_nl(struct slsi_dev *sdev, struct slsi_nan_range_response_cfg *cfg, - const struct nlattr *iter, int nl_attr_id) -{ - switch (nl_attr_id) { - case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PUBLISH_ID: - cfg->publish_id = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_REQUESTOR_ID: - cfg->requestor_instance_id = nla_get_u32(iter); - break; - - case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PEER_ADDR: - memcpy(cfg->peer_addr, nla_data(iter), ETH_ALEN); - break; - - case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_RANGING_RESPONSE: - cfg->ranging_response = nla_get_u8(iter); - break; - - default: - return -EINVAL; - } - return 0; -} - -static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_enable_req *hal_req, - const void *data, int len) -{ - int type, tmp; - const struct nlattr *iter; - - memset(hal_req, 0, sizeof(*hal_req)); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_MASTER_PREF: - hal_req->master_pref = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_CLUSTER_LOW: - hal_req->cluster_low = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_CLUSTER_HIGH: - hal_req->cluster_high = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUPPORT_5G_VAL: - hal_req->support_5g_val = nla_get_u8(iter); - hal_req->config_support_5g = 1; - break; - - case NAN_REQ_ATTR_SID_BEACON_VAL: - hal_req->sid_beacon_val = nla_get_u8(iter); - hal_req->config_sid_beacon = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL: - hal_req->rssi_close_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_rssi_close = 1; - break; - - case NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL: - hal_req->rssi_middle_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_rssi_middle = 1; - break; - - case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL: - hal_req->rssi_proximity_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_rssi_proximity = 1; - break; - - case NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL: - hal_req->hop_count_limit_val = nla_get_u8(iter); - hal_req->config_hop_count_limit = 1; - break; - - case NAN_REQ_ATTR_SUPPORT_2G4_VAL: - hal_req->support_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_support = 1; - break; - - case NAN_REQ_ATTR_BEACONS_2G4_VAL: - hal_req->beacon_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_beacons = 1; - break; - - case NAN_REQ_ATTR_SDF_2G4_VAL: - hal_req->sdf_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_sdf = 1; - break; - - case NAN_REQ_ATTR_BEACON_5G_VAL: - hal_req->beacon_5g_val = nla_get_u8(iter); - hal_req->config_5g_beacons = 1; - break; - - case NAN_REQ_ATTR_SDF_5G_VAL: - hal_req->sdf_5g_val = nla_get_u8(iter); - hal_req->config_5g_sdf = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL: - hal_req->rssi_close_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_close = 1; - break; - - case NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL: - hal_req->rssi_middle_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_middle = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL: - hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_close_proximity = 1; - break; - - case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL: - hal_req->rssi_window_size_val = nla_get_u8(iter); - hal_req->config_rssi_window_size = 1; - break; - - case NAN_REQ_ATTR_OUI_VAL: - hal_req->oui_val = nla_get_u32(iter); - hal_req->config_oui = 1; - break; - - case NAN_REQ_ATTR_MAC_ADDR_VAL: - memcpy(hal_req->intf_addr_val, nla_data(iter), ETH_ALEN); - hal_req->config_intf_addr = 1; - break; - - case NAN_REQ_ATTR_CLUSTER_VAL: - hal_req->config_cluster_attribute_val = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME: - memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter), - sizeof(hal_req->scan_params_val.dwell_time)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD: - memcpy(hal_req->scan_params_val.scan_period, nla_data(iter), - sizeof(hal_req->scan_params_val.scan_period)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL: - hal_req->random_factor_force_val = nla_get_u8(iter); - hal_req->config_random_factor_force = 1; - break; - - case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL: - hal_req->hop_count_force_val = nla_get_u8(iter); - hal_req->config_hop_count_force = 1; - break; - - case NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL: - hal_req->channel_24g_val = nla_get_u32(iter); - hal_req->config_24g_channel = 1; - break; - - case NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL: - hal_req->channel_5g_val = nla_get_u8(iter); - hal_req->config_5g_channel = 1; - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL: - hal_req->subscribe_sid_beacon_val = nla_get_u8(iter); - hal_req->config_subscribe_sid_beacon = 1; - break; - - case NAN_REQ_ATTR_DW_2G4_INTERVAL: - hal_req->dw_2dot4g_interval_val = nla_get_u8(iter); - /* valid range for 2.4G is 1-5 */ - if (hal_req->dw_2dot4g_interval_val > 0 && hal_req->dw_2dot4g_interval_val < 5) - hal_req->config_2dot4g_dw_band = 1; - break; - - case NAN_REQ_ATTR_DW_5G_INTERVAL: - hal_req->dw_5g_interval_val = nla_get_u8(iter); - /* valid range for 5g is 0-5 */ - if (hal_req->dw_5g_interval_val < 5) - hal_req->config_5g_dw_band = 1; - break; - - case NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL: - hal_req->disc_mac_addr_rand_interval_sec = nla_get_u32(iter); - break; - - default: - SLSI_ERR(sdev, "Unexpected NAN enable attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct slsi_hal_nan_enable_req hal_req; - int ret; - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - u8 nan_vif_mac_address[ETH_ALEN]; - u8 broadcast_mac[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "No NAN interface\n"); - ret = -ENOTSUPP; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - if (!slsi_dev_nan_supported(sdev)) { - SLSI_ERR(sdev, "NAN not allowed(mib:%d)\n", sdev->nan_enabled); - ret = WIFI_HAL_ERROR_NOT_SUPPORTED; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - ndev_vif = netdev_priv(dev); - - reply_status = slsi_nan_enable_get_nl_params(sdev, &hal_req, data, len); - if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { - ret = -EINVAL; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->activated) { - ret = -EINVAL; - SLSI_DBG1(sdev, SLSI_GSCAN, "Already Enabled. Req Rejected\n"); - goto exit_with_mutex; - } - ndev_vif->vif_type = FAPI_VIFTYPE_NAN; - - if (hal_req.config_intf_addr) - ether_addr_copy(nan_vif_mac_address, hal_req.intf_addr_val); - else - slsi_nan_get_mac(sdev, nan_vif_mac_address); - - ret = slsi_mlme_add_vif(sdev, dev, nan_vif_mac_address, broadcast_mac); - if (ret) { - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - SLSI_ERR(sdev, "failed to set unsync vif. Cannot start NAN\n"); - } else { - ret = slsi_mlme_nan_enable(sdev, dev, &hal_req); - if (ret) { - SLSI_ERR(sdev, "failed to enable NAN.\n"); - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - slsi_mlme_del_vif(sdev, dev); - ndev_vif->activated = false; - ndev_vif->nan.subscribe_id_map = 0; - ndev_vif->nan.publish_id_map = 0; - } else { - slsi_vif_activated(sdev, dev); - } - } - -exit_with_mutex: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_ENABLED, 0, NULL); - return ret; -} - -int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - - if (dev) { - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->activated) { - slsi_mlme_del_vif(sdev, dev); - ndev_vif->activated = false; - ndev_vif->nan.subscribe_id_map = 0; - ndev_vif->nan.publish_id_map = 0; - } else { - SLSI_WARN(sdev, "NAN FWif not active!!"); - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } else { - SLSI_WARN(sdev, "No NAN interface!!"); - } - - slsi_vendor_nan_command_reply(wiphy, SLSI_HAL_NAN_STATUS_SUCCESS, 0, NAN_RESPONSE_DISABLED, 0, NULL); - - return 0; -} - -static int slsi_nan_publish_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_publish_req *hal_req, - const void *data, int len) -{ - int type, tmp, r; - const struct nlattr *iter; - - memset(hal_req, 0, sizeof(*hal_req)); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_PUBLISH_ID: - hal_req->publish_id = nla_get_u16(iter); - break; - case NAN_REQ_ATTR_PUBLISH_TTL: - hal_req->ttl = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_PERIOD: - hal_req->period = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_TYPE: - hal_req->publish_type = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_TX_TYPE: - hal_req->tx_type = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_COUNT: - hal_req->publish_count = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN: - hal_req->service_name_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME: - memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len); - break; - - case NAN_REQ_ATTR_PUBLISH_MATCH_ALGO: - hal_req->publish_match_indicator = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN: - hal_req->service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO: - memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); - break; - - case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN: - hal_req->rx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER: - memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len); - break; - - case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN: - hal_req->tx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER: - memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len); - break; - - case NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG: - hal_req->rssi_threshold_flag = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_CONN_MAP: - hal_req->connmap = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG: - hal_req->recv_indication_cfg = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SDEA_LEN: - hal_req->sdea_service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SDEA: - memcpy(hal_req->sdea_service_specific_info, nla_data(iter), - hal_req->sdea_service_specific_info_len); - break; - - case NAN_REQ_ATTR_RANGING_AUTO_RESPONSE: - hal_req->ranging_auto_response = nla_get_u8(iter); - break; - - default: - r = slsi_nan_get_sdea_params_nl(sdev, &hal_req->sdea_params, iter, type); - if (r) - r = slsi_nan_get_ranging_cfg_nl(sdev, &hal_req->ranging_cfg, iter, type); - if (r) - r = slsi_nan_get_security_info_nl(sdev, &hal_req->sec_info, iter, type); - if (r) - r = slsi_nan_get_range_resp_cfg_nl(sdev, &hal_req->range_response_cfg, iter, type); - if (r) { - SLSI_ERR(sdev, "Unexpected NAN publish attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct slsi_hal_nan_publish_req *hal_req; - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - int ret; - u32 reply_status; - u32 publish_id = 0; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!\n"); - ret = -EINVAL; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL); - if (!hal_req) { - SLSI_ERR(sdev, "failed to alloc hal_req\n"); - reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE; - ret = -ENOMEM; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_publish_get_nl_params(sdev, hal_req, data, len); - if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { - kfree(hal_req); - ret = -EINVAL; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - SLSI_WARN(sdev, "NAN vif not activated\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - goto exit_with_lock; - } - - if (!hal_req->publish_id) { - hal_req->publish_id = slsi_nan_get_new_publish_id(ndev_vif); - } else if (!slsi_nan_is_publish_id_active(ndev_vif, hal_req->publish_id)) { - SLSI_WARN(sdev, "Publish id %d not found. map:%x\n", hal_req->publish_id, - ndev_vif->nan.publish_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - ret = -EINVAL; - goto exit_with_lock; - } - - if (hal_req->publish_id) { - ret = slsi_mlme_nan_publish(sdev, dev, hal_req, hal_req->publish_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - else - publish_id = hal_req->publish_id; - } else { - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - SLSI_WARN(sdev, "Too Many concurrent PUBLISH REQ(map:%x)\n", - ndev_vif->nan.publish_id_map); - ret = -ENOTSUPP; - } -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - kfree(hal_req); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH, publish_id, NULL); - return ret; -} - -int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, - const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - int type, tmp, ret = 0; - u16 publish_id = 0; - const struct nlattr *iter; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = -EINVAL; - goto exit; - } - - ndev_vif = netdev_priv(dev); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_PUBLISH_ID: - publish_id = nla_get_u16(iter); - break; - default: - SLSI_ERR(sdev, "Unexpected NAN publishcancel attribute TYPE:%d\n", type); - } - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - goto exit_with_lock; - } - if (!publish_id || !slsi_nan_is_publish_id_active(ndev_vif, publish_id)) { - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - SLSI_WARN(sdev, "Publish_id(%d) not active. map:%x\n", - publish_id, ndev_vif->nan.publish_id_map); - } else { - ret = slsi_mlme_nan_publish(sdev, dev, NULL, publish_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - } -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH_CANCEL, publish_id, NULL); - return ret; -} - -static int slsi_nan_subscribe_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_subscribe_req *hal_req, - const void *data, int len) -{ - int type, tmp, r; - const struct nlattr *iter; - - memset(hal_req, 0, sizeof(*hal_req)); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_SUBSCRIBE_ID: - hal_req->subscribe_id = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TTL: - hal_req->ttl = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_PERIOD: - hal_req->period = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TYPE: - hal_req->subscribe_type = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE: - hal_req->service_response_filter = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE: - hal_req->service_response_include = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER: - hal_req->use_service_response_filter = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED: - hal_req->ssi_required_for_match_indication = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR: - hal_req->subscribe_match_indicator = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_COUNT: - hal_req->subscribe_count = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN: - hal_req->service_name_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME: - memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN: - hal_req->service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO: - memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN: - hal_req->rx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER: - memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN: - hal_req->tx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER: - memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG: - hal_req->rssi_threshold_flag = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP: - hal_req->connmap = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT: - hal_req->num_intf_addr_present = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR: - memcpy(hal_req->intf_addr, nla_data(iter), hal_req->num_intf_addr_present * ETH_ALEN); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG: - hal_req->recv_indication_cfg = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SDEA_LEN: - hal_req->sdea_service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SDEA: - memcpy(hal_req->sdea_service_specific_info, nla_data(iter), - hal_req->sdea_service_specific_info_len); - break; - - case NAN_REQ_ATTR_RANGING_AUTO_RESPONSE: - hal_req->ranging_auto_response = nla_get_u8(iter); - break; - - default: - r = slsi_nan_get_sdea_params_nl(sdev, &hal_req->sdea_params, iter, type); - if (r) - r = slsi_nan_get_ranging_cfg_nl(sdev, &hal_req->ranging_cfg, iter, type); - if (r) - r = slsi_nan_get_security_info_nl(sdev, &hal_req->sec_info, iter, type); - if (r) - r = slsi_nan_get_range_resp_cfg_nl(sdev, &hal_req->range_response_cfg, iter, type); - if (r) { - SLSI_ERR(sdev, "Unexpected NAN subscribe attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - struct slsi_hal_nan_subscribe_req *hal_req; - int ret; - u32 reply_status; - u32 subscribe_id = 0; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = -EINVAL; - goto exit; - } - - hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL); - if (!hal_req) { - SLSI_ERR(sdev, "Failed to alloc hal_req structure!!!\n"); - reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE; - ret = -ENOMEM; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_subscribe_get_nl_params(sdev, hal_req, data, len); - if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { - kfree(hal_req); - ret = -EINVAL; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - SLSI_WARN(sdev, "NAN vif not activated\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - goto exit_with_lock; - } - - if (!hal_req->subscribe_id) { - hal_req->subscribe_id = slsi_nan_get_new_subscribe_id(ndev_vif); - } else if (!slsi_nan_is_subscribe_id_active(ndev_vif, hal_req->subscribe_id)) { - SLSI_WARN(sdev, "Subscribe id %d not found. map:%x\n", hal_req->subscribe_id, - ndev_vif->nan.subscribe_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - ret = -EINVAL; - goto exit_with_lock; - } - - ret = slsi_mlme_nan_subscribe(sdev, dev, hal_req, hal_req->subscribe_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - else - subscribe_id = hal_req->subscribe_id; - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - kfree(hal_req); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE, subscribe_id, NULL); - return ret; -} - -int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - int type, tmp, ret = WIFI_HAL_ERROR_UNKNOWN; - u16 subscribe_id = 0; - const struct nlattr *iter; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - goto exit; - } - - ndev_vif = netdev_priv(dev); - - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_SUBSCRIBE_ID: - subscribe_id = nla_get_u16(iter); - break; - default: - SLSI_ERR(sdev, "Unexpected NAN subscribecancel attribute TYPE:%d\n", type); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM; - goto exit; - } - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->activated) { - if (!subscribe_id || !slsi_nan_is_subscribe_id_active(ndev_vif, subscribe_id)) { - SLSI_WARN(sdev, "subscribe_id(%d) not active. map:%x\n", - subscribe_id, ndev_vif->nan.subscribe_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - } else { - ret = slsi_mlme_nan_subscribe(sdev, dev, NULL, subscribe_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - } - } else { - SLSI_ERR(sdev, "vif not activated\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE_CANCEL, subscribe_id, NULL); - return ret; -} - -static int slsi_nan_followup_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_transmit_followup_req *hal_req, - const void *data, int len) -{ - int type, tmp; - const struct nlattr *iter; - - memset(hal_req, 0, sizeof(*hal_req)); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_FOLLOWUP_ID: - hal_req->publish_subscribe_id = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID: - hal_req->requestor_instance_id = nla_get_u32(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_ADDR: - memcpy(hal_req->addr, nla_data(iter), ETH_ALEN); - break; - - case NAN_REQ_ATTR_FOLLOWUP_PRIORITY: - hal_req->priority = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW: - hal_req->dw_or_faw = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN: - hal_req->service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME: - memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); - break; - - case NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG: - hal_req->recv_indication_cfg = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SDEA_LEN: - hal_req->sdea_service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SDEA: - memcpy(hal_req->sdea_service_specific_info, nla_data(iter), - hal_req->sdea_service_specific_info_len); - break; - - default: - SLSI_ERR(sdev, "Unexpected NAN followup attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - struct slsi_hal_nan_transmit_followup_req hal_req; - int ret; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - ret = -EINVAL; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_followup_get_nl_params(sdev, &hal_req, data, len); - if (reply_status) { - ret = -EINVAL; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - SLSI_WARN(sdev, "NAN vif not activated\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - goto exit_with_lock; - } - - if (!hal_req.publish_subscribe_id || - !(slsi_nan_is_subscribe_id_active(ndev_vif, hal_req.publish_subscribe_id) || - slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_subscribe_id))) { - SLSI_WARN(sdev, "publish/Subscribe id %d not found. map:%x\n", hal_req.publish_subscribe_id, - ndev_vif->nan.subscribe_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - ret = -EINVAL; - goto exit_with_lock; - } - - ret = slsi_mlme_nan_tx_followup(sdev, dev, &hal_req); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_TRANSMIT_FOLLOWUP, 0, NULL); - return ret; -} - -static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_config_req *hal_req, - const void *data, int len) -{ - int type, type1, tmp, tmp1, disc_attr_idx = 0, famchan_idx = 0; - const struct nlattr *iter, *iter1; - struct slsi_hal_nan_post_discovery_param *disc_attr; - struct slsi_hal_nan_further_availability_channel *famchan; - - memset(hal_req, 0, sizeof(*hal_req)); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_SID_BEACON_VAL: - hal_req->sid_beacon = nla_get_u8(iter); - hal_req->config_sid_beacon = 1; - break; - - case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL: - hal_req->rssi_proximity = nla_get_u8(iter); - hal_req->config_rssi_proximity = 1; - break; - - case NAN_REQ_ATTR_MASTER_PREF: - hal_req->master_pref = nla_get_u8(iter); - hal_req->config_master_pref = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL: - hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_close_proximity = 1; - break; - - case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL: - hal_req->rssi_window_size_val = nla_get_u8(iter); - hal_req->config_rssi_window_size = 1; - break; - - case NAN_REQ_ATTR_CLUSTER_VAL: - hal_req->config_cluster_attribute_val = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME: - memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter), - sizeof(hal_req->scan_params_val.dwell_time)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD: - memcpy(hal_req->scan_params_val.scan_period, nla_data(iter), - sizeof(hal_req->scan_params_val.scan_period)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL: - hal_req->random_factor_force_val = nla_get_u8(iter); - hal_req->config_random_factor_force = 1; - break; - - case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL: - hal_req->hop_count_force_val = nla_get_u8(iter); - hal_req->config_hop_count_force = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX: - hal_req->conn_capability_val.payload_transmit_flag = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_WFD: - hal_req->conn_capability_val.is_wfd_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_WFDS: - hal_req->conn_capability_val.is_wfds_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_TDLS: - hal_req->conn_capability_val.is_tdls_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_MESH: - hal_req->conn_capability_val.is_mesh_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_IBSS: - hal_req->conn_capability_val.is_ibss_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA: - hal_req->conn_capability_val.wlan_infra_field = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES: - hal_req->num_config_discovery_attr = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_DISCOVERY_ATTR_VAL: - if (disc_attr_idx >= hal_req->num_config_discovery_attr) { - SLSI_ERR(sdev, - "disc attr(%d) > num disc attr(%d)\n", - disc_attr_idx + 1, hal_req->num_config_discovery_attr); - return -EINVAL; - } - disc_attr = &hal_req->discovery_attr_val[disc_attr_idx]; - disc_attr_idx++; - nla_for_each_nested(iter1, iter, tmp1) { - type1 = nla_type(iter1); - switch (type1) { - case NAN_REQ_ATTR_CONN_TYPE: - disc_attr->type = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_NAN_ROLE: - disc_attr->role = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_TRANSMIT_FREQ: - disc_attr->transmit_freq = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_AVAILABILITY_DURATION: - disc_attr->duration = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_AVAILABILITY_INTERVAL: - disc_attr->avail_interval_bitmap = nla_get_u32(iter1); - break; - - case NAN_REQ_ATTR_MAC_ADDR_VAL: - memcpy(disc_attr->addr, nla_data(iter1), ETH_ALEN); - break; - - case NAN_REQ_ATTR_MESH_ID_LEN: - disc_attr->mesh_id_len = nla_get_u16(iter1); - break; - - case NAN_REQ_ATTR_MESH_ID: - memcpy(disc_attr->mesh_id, nla_data(iter1), disc_attr->mesh_id_len); - break; - - case NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN: - disc_attr->infrastructure_ssid_len = nla_get_u16(iter1); - break; - - case NAN_REQ_ATTR_INFRASTRUCTURE_SSID: - memcpy(disc_attr->infrastructure_ssid_val, nla_data(iter1), - disc_attr->infrastructure_ssid_len); - break; - } - } - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES: - hal_req->fam_val.numchans = nla_get_u8(iter); - hal_req->config_fam = 1; - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_VAL: - hal_req->config_fam = 1; - if (famchan_idx >= hal_req->fam_val.numchans) { - SLSI_ERR(sdev, - "famchan attr(%d) > numchans(%d)\n", - famchan_idx + 1, hal_req->fam_val.numchans); - return -EINVAL; - } - famchan = &hal_req->fam_val.famchan[famchan_idx]; - famchan_idx++; - nla_for_each_nested(iter1, iter, tmp1) { - type1 = nla_type(iter1); - switch (type1) { - case NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL: - famchan->entry_control = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS: - famchan->class_val = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN: - famchan->channel = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID: - famchan->mapid = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP: - famchan->avail_interval_bitmap = nla_get_u32(iter1); - break; - } - } - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL: - hal_req->subscribe_sid_beacon_val = nla_get_u8(iter); - hal_req->config_subscribe_sid_beacon = 1; - break; - - case NAN_REQ_ATTR_DW_2G4_INTERVAL: - hal_req->dw_2dot4g_interval_val = nla_get_u8(iter); - /* valid range for 2.4G is 1-5 */ - if (hal_req->dw_2dot4g_interval_val > 0 && hal_req->dw_2dot4g_interval_val < 6) - hal_req->config_2dot4g_dw_band = 1; - break; - - case NAN_REQ_ATTR_DW_5G_INTERVAL: - hal_req->dw_5g_interval_val = nla_get_u8(iter); - /* valid range for 5g is 0-5 */ - if (hal_req->dw_5g_interval_val < 6) - hal_req->config_5g_dw_band = 1; - break; - - case NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL: - hal_req->disc_mac_addr_rand_interval_sec = nla_get_u8(iter); - break; - - default: - SLSI_ERR(sdev, "Unexpected NAN config attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - struct slsi_hal_nan_config_req hal_req; - int ret; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - ret = -EINVAL; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_config_get_nl_params(sdev, &hal_req, data, len); - if (reply_status) { - ret = -EINVAL; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - SLSI_WARN(sdev, "NAN vif not activated\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - } else { - ret = slsi_mlme_nan_set_config(sdev, dev, &hal_req); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_CONFIG, 0, NULL); - return ret; -} - -int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - struct slsi_hal_nan_capabilities nan_capabilities; - int ret = 0, i; - struct slsi_mib_value *values = NULL; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_CLUSTERS, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_PUBLISHES, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_SUBSCRIBES, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_NAME_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_MATCH_FILTER_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_TOTAL_MATCH_FILTER_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_SPECIFIC_INFO_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_VSA_DATA_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_MESH_DATA_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_NDI_INTERFACES, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_NDP_SESSIONS, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_APP_INFO_LENGTH, { 0, 0 } } }; - u32 *capabilities_mib_val[] = { &nan_capabilities.max_concurrent_nan_clusters, - &nan_capabilities.max_publishes, - &nan_capabilities.max_subscribes, - &nan_capabilities.max_service_name_len, - &nan_capabilities.max_match_filter_len, - &nan_capabilities.max_total_match_filter_len, - &nan_capabilities.max_service_specific_info_len, - &nan_capabilities.max_vsa_data_len, - &nan_capabilities.max_mesh_data_len, - &nan_capabilities.max_ndi_interfaces, - &nan_capabilities.max_ndp_sessions, - &nan_capabilities.max_app_info_len }; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = -EINVAL; - goto exit; - } - - ndev_vif = netdev_priv(dev); - - /* Expect each mib length in response is 11 */ - mibrsp.dataLength = 11 * ARRAY_SIZE(get_values); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE; - ret = -ENOMEM; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp); - if (!values) { - ret = 0xFFFFFFFF; - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - goto exit_with_mibrsp; - } - - for (i = 0; i < (int)ARRAY_SIZE(get_values); i++) { - if (values[i].type == SLSI_MIB_TYPE_UINT) { - *capabilities_mib_val[i] = values[i].u.uintValue; - SLSI_DBG2(sdev, SLSI_GSCAN, "MIB value = %ud\n", *capabilities_mib_val[i]); - } else { - SLSI_ERR(sdev, "invalid type(%d). iter:%d\n", values[i].type, i); - ret = 0xFFFFFFFF; - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - *capabilities_mib_val[i] = 0; - } - } - - kfree(values); -exit_with_mibrsp: - kfree(mibrsp.data); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_GET_CAPABILITIES, 0, &nan_capabilities); - return ret; -} - -void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct sk_buff *nl_skb = NULL; - int res = 0; - u16 event, identifier, evt_reason; - u8 *mac_addr; - u16 hal_event; - struct netdev_vif *ndev_vif; - enum slsi_nan_disc_event_type disc_event_type = 0; - - ndev_vif = netdev_priv(dev); - event = fapi_get_u16(skb, u.mlme_nan_event_ind.event); - identifier = fapi_get_u16(skb, u.mlme_nan_event_ind.identifier); - mac_addr = fapi_get_buff(skb, u.mlme_nan_event_ind.address_or_identifier); - - switch (fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code)) { - case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_TIMEOUT: - case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_COUNT_REACHED: - case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_DISCOVERY_SHUTDOWN: - case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_USER_REQUEST: - case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_SUCCESS: - evt_reason = SLSI_HAL_NAN_STATUS_SUCCESS; - break; - case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_FAILURE: - evt_reason = SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE; - break; - default: - evt_reason = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - break; - } - - switch (event) { - case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED: - hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED: - hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED: - hal_event = SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_ADDRESS_CHANGED: - disc_event_type = NAN_EVENT_ID_DISC_MAC_ADDR; - hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_STARTED: - disc_event_type = NAN_EVENT_ID_STARTED_CLUSTER; - hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_JOINED: - disc_event_type = NAN_EVENT_ID_JOINED_CLUSTER; - hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_TRANSMIT_FOLLOWUP: - hal_event = SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS; - break; - default: - return; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(hal_event), hal_event); -#endif - -#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE) - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL); -#else - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL); -#endif - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - return; - } - - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_STATUS, evt_reason); - switch (hal_event) { - case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT: - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier); - ndev_vif->nan.publish_id_map &= (u32)~BIT(identifier); - break; - case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT: - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier); - break; - case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT: - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier); - ndev_vif->nan.subscribe_id_map &= (u32)~BIT(identifier); - break; - case SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT: - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, disc_event_type); - res |= nla_put(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, ETH_ALEN, mac_addr); - break; - } - - if (res) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - return; - } - - cfg80211_vendor_event(nl_skb, GFP_KERNEL); -} - -void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 tag_id, tag_len; - u8 *ptr; - struct slsi_hal_nan_followup_ind *hal_evt; - struct sk_buff *nl_skb; - int res; - int sig_data_len; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - - sig_data_len = fapi_get_datalen(skb); - if (sig_data_len <= 4) { - SLSI_ERR(sdev, "Invalid data len(%d)\n", sig_data_len); - return; - } - - hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL); - if (!hal_evt) { - SLSI_ERR(sdev, "No memory for followup_ind\n"); - return; - } - memset(hal_evt, 0, sizeof(*hal_evt)); - - hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.publish_subscribe_id); - hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.match_id); - ether_addr_copy(hal_evt->addr, - fapi_get_buff(skb, u.mlme_nan_followup_ind.peer_nan_management_interface_address)); - - ptr = fapi_get_data(skb); - tag_id = le16_to_cpu(*(u16 *)ptr); - tag_len = le16_to_cpu(*(u16 *)(ptr + 2)); - - while (sig_data_len >= tag_len + 4) { - if (tag_id == SLSI_NAN_TLV_TAG_SERVICE_SPECIFIC_INFO) { - hal_evt->service_specific_info_len = tag_len > SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN ? - SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN : tag_len; - memcpy(hal_evt->service_specific_info, ptr + 4, hal_evt->service_specific_info_len); - } else if (tag_id == SLSI_NAN_TLV_TAG_EXT_SERVICE_SPECIFIC_INFO) { - if (tag_len > SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN) - hal_evt->sdea_service_specific_info_len = SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN; - else - hal_evt->sdea_service_specific_info_len = tag_len; - memcpy(hal_evt->sdea_service_specific_info, ptr + 4, hal_evt->sdea_service_specific_info_len); - } else { - SLSI_WARN(sdev, "Skip processing TLV %d\n", tag_id); - } - sig_data_len -= tag_len + 4; - ptr += tag_len + 4; - if (sig_data_len > 4) { - tag_id = le16_to_cpu(*(u16 *)ptr); - tag_len = le16_to_cpu(*(u16 *)(ptr + 2)); - } else { - tag_id = 0; - tag_len = 0; - } - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(SLSI_NL80211_NAN_FOLLOWUP_EVENT), SLSI_NL80211_NAN_FOLLOWUP_EVENT); -#endif -#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE) - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT, - GFP_KERNEL); -#else - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT, - GFP_KERNEL); -#endif - - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - kfree(hal_evt); - return; - } - - res = nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID, - cpu_to_le16(hal_evt->publish_subscribe_id)); - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID, - cpu_to_le16(hal_evt->requestor_instance_id)); - res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_ADDR, ETH_ALEN, hal_evt->addr); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, hal_evt->dw_or_faw); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len); - if (hal_evt->service_specific_info_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len, - hal_evt->service_specific_info); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_SDEA_LEN, hal_evt->sdea_service_specific_info_len); - if (hal_evt->sdea_service_specific_info_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_SDEA, hal_evt->sdea_service_specific_info_len, - hal_evt->sdea_service_specific_info); - - if (res) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); - kfree(hal_evt); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - return; - } - - cfg80211_vendor_event(nl_skb, GFP_KERNEL); - kfree(hal_evt); -} - -void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 tag_id, tag_len; - u8 *ptr; - const u8 *tag_data_ptr; - int sig_data_len; - struct slsi_hal_nan_match_ind *hal_evt; - struct sk_buff *nl_skb; - int res; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - - sig_data_len = fapi_get_datalen(skb); - if (sig_data_len <= 4) { - SLSI_ERR(sdev, "Invalid data len(%d)\n", sig_data_len); - return; - } - - hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL); - if (!hal_evt) { - SLSI_ERR(sdev, "No memory for service_ind\n"); - return; - } - - memset(hal_evt, 0, sizeof(*hal_evt)); - hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_service_ind.publish_subscribe_id); - hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_service_ind.match_id); - hal_evt->ranging_event_type = fapi_get_u16(skb, u.mlme_nan_service_ind.rangingindicationtype); - hal_evt->range_measurement_mm = 10 * fapi_get_u16(skb, u.mlme_nan_service_ind.ranging_measurement); - - ptr = fapi_get_data(skb); - tag_id = le16_to_cpu(*(u16 *)ptr); - tag_len = le16_to_cpu(*(u16 *)(ptr + 2)); - tag_data_ptr = ptr + 4; - - while (sig_data_len >= tag_len + 4) { - switch (tag_id) { - case SLSI_NAN_TLV_TAG_MATCH_IND: - if (tag_len < 0x11) { - SLSI_WARN(sdev, "Invalid taglen(%d) for SLSI_NAN_TLV_TAG_MATCH_IND\n", tag_len); - break; - } - ether_addr_copy(hal_evt->addr, tag_data_ptr); - tag_data_ptr += ETH_ALEN; - hal_evt->match_occurred_flag = le16_to_cpu(*(u16 *)tag_data_ptr); - tag_data_ptr += 2; - hal_evt->out_of_resource_flag = le16_to_cpu(*(u16 *)tag_data_ptr); - tag_data_ptr += 2; - hal_evt->rssi_value = *tag_data_ptr; - tag_data_ptr++; - hal_evt->sec_info.cipher_type = *tag_data_ptr; - break; - case SLSI_NAN_TLV_TAG_SERVICE_SPECIFIC_INFO: - hal_evt->service_specific_info_len = tag_len > SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN ? - SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN : tag_len; - memcpy(hal_evt->service_specific_info, tag_data_ptr, hal_evt->service_specific_info_len); - break; - case SLSI_NAN_TLV_TAG_EXT_SERVICE_SPECIFIC_INFO: - if (tag_len > SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN) - hal_evt->sdea_service_specific_info_len = SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN; - else - hal_evt->sdea_service_specific_info_len = tag_len; - memcpy(hal_evt->sdea_service_specific_info, tag_data_ptr, hal_evt->sdea_service_specific_info_len); - break; - case SLSI_NAN_TLV_TAG_DATA_PATH_SECURITY: - if (tag_len < 7) { - SLSI_WARN(sdev, "Invalid taglen(%d) for SLSI_NAN_TLV_TAG_DATA_PATH_SECURITY\n", tag_len); - break; - } - hal_evt->sec_info.key_info.key_type = *tag_data_ptr; - tag_data_ptr++; - hal_evt->sec_info.cipher_type = *tag_data_ptr; - tag_data_ptr++; - break; - default: - SLSI_WARN(sdev, "Skip processing TLV %d\n", tag_id); - break; - } - - sig_data_len -= tag_len + 4; - ptr += tag_len + 4; - if (sig_data_len > 4) { - tag_id = le16_to_cpu(*(u16 *)ptr); - tag_len = le16_to_cpu(*(u16 *)(ptr + 2)); - } else { - tag_id = 0; - tag_len = 0; - } - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(SLSI_NL80211_NAN_MATCH_EVENT), SLSI_NL80211_NAN_MATCH_EVENT); -#endif -#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE) - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, - GFP_KERNEL); -#else - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, GFP_KERNEL); -#endif - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - kfree(hal_evt); - return; - } - res = nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, hal_evt->publish_subscribe_id); - res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, hal_evt->requestor_instance_id); - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, hal_evt->addr); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len); - if (hal_evt->service_specific_info_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len, - hal_evt->service_specific_info); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, hal_evt->sdf_match_filter_len); - if (hal_evt->sdf_match_filter_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, hal_evt->sdf_match_filter_len, - hal_evt->sdf_match_filter); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_SDEA_LEN, hal_evt->sdea_service_specific_info_len); - if (hal_evt->sdea_service_specific_info_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_SDEA, hal_evt->sdea_service_specific_info_len, - hal_evt->sdea_service_specific_info); - - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, hal_evt->match_occurred_flag); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, hal_evt->out_of_resource_flag); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_RSSI_VALUE, hal_evt->rssi_value); - res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_RANGE_MEASUREMENT_MM, hal_evt->range_measurement_mm); - res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_RANGEING_EVENT_TYPE, hal_evt->ranging_event_type); - res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_SECURITY_CIPHER_TYPE, hal_evt->sec_info.cipher_type); - - if (res) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - kfree(hal_evt); - return; - } - - cfg80211_vendor_event(nl_skb, GFP_KERNEL); - kfree(hal_evt); -} diff --git a/drivers/net/wireless/scsc/nl80211_vendor_nan.h b/drivers/net/wireless/scsc/nl80211_vendor_nan.h deleted file mode 100755 index 126ec9f15a7c..000000000000 --- a/drivers/net/wireless/scsc/nl80211_vendor_nan.h +++ /dev/null @@ -1,906 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#ifndef __SLSI_NL80211_VENDOR_NAN_H_ -#define __SLSI_NL80211_VENDOR_NAN_H_ - -#define SLSI_NAN_TLV_TAG_CONFIGURATION 0x0101 -#define SLSI_NAN_TLV_TAG_2G4_BAND_SPECIFIC_CONFIG 0x0102 -#define SLSI_NAN_TLV_TAG_5G_BAND_SPECIFIC_CONFIG 0x0103 -#define SLSI_NAN_TLV_TAG_SUBSCRIBE_SPECIFIC 0x0104 -#define SLSI_NAN_TLV_TAG_DISCOVERY_COMMON_SPECIFIC 0x0105 -#define SLSI_NAN_TLV_TAG_SERVICE_NAME 0x0106 -#define SLSI_NAN_TLV_TAG_SERVICE_SPECIFIC_INFO 0x0107 -#define SLSI_NAN_TLV_TAG_EXT_SERVICE_SPECIFIC_INFO 0x0108 -#define SLSI_NAN_TLV_TAG_RX_MATCH_FILTER 0x0109 -#define SLSI_NAN_TLV_TAG_TX_MATCH_FILTER 0x010a -#define SLSI_NAN_TLV_TAG_MATCH_FILTER 0x010b -#define SLSI_NAN_TLV_TAG_INTERFACE_ADDRESS_SET 0x010c -#define SLSI_NAN_TLV_TAG_MATCH_IND 0x010d -#define SLSI_NAN_TLV_TAG_DATA_PATH_SECURITY 0x010e -#define SLSI_NAN_TLV_TAG_APP_INFO 0x010f -#define SLSI_NAN_TLV_TAG_RANGING 0x0110 - -enum SLSI_NAN_REPLY_ATTRIBUTES { - NAN_REPLY_ATTR_STATUS_TYPE, - NAN_REPLY_ATTR_VALUE, - NAN_REPLY_ATTR_RESPONSE_TYPE, - NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, - NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER, - NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, - NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, - NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, - NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, - NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN, - NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN, - NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, - NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, - NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, - NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, - NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN -}; - -enum SLSI_NAN_REQ_ATTRIBUTES { - NAN_REQ_ATTR_MASTER_PREF, - NAN_REQ_ATTR_CLUSTER_LOW, - NAN_REQ_ATTR_CLUSTER_HIGH, - NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL, - NAN_REQ_ATTR_SID_BEACON_VAL, - NAN_REQ_ATTR_SUPPORT_2G4_VAL, - NAN_REQ_ATTR_SUPPORT_5G_VAL, - NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL, - NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL, - NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL, - NAN_REQ_ATTR_BEACONS_2G4_VAL = 10, - NAN_REQ_ATTR_SDF_2G4_VAL, - NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL, - NAN_REQ_ATTR_RSSI_PROXIMITY_VAL, - NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL, - NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL, - NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL, - NAN_REQ_ATTR_RSSI_PROXIMITY_5G_VAL, - NAN_REQ_ATTR_BEACON_5G_VAL, - NAN_REQ_ATTR_SDF_5G_VAL, - NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL = 20, - NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL, - NAN_REQ_ATTR_OUI_VAL, - NAN_REQ_ATTR_MAC_ADDR_VAL, - NAN_REQ_ATTR_CLUSTER_VAL, - NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME, - NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD, - NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL, - NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL, - NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX, - NAN_REQ_ATTR_CONN_CAPABILITY_IBSS = 30, - NAN_REQ_ATTR_CONN_CAPABILITY_WFD, - NAN_REQ_ATTR_CONN_CAPABILITY_WFDS, - NAN_REQ_ATTR_CONN_CAPABILITY_TDLS, - NAN_REQ_ATTR_CONN_CAPABILITY_MESH, - NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA, - NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES, - NAN_REQ_ATTR_DISCOVERY_ATTR_VAL, - NAN_REQ_ATTR_CONN_TYPE, - NAN_REQ_ATTR_NAN_ROLE, - NAN_REQ_ATTR_TRANSMIT_FREQ = 40, - NAN_REQ_ATTR_AVAILABILITY_DURATION, - NAN_REQ_ATTR_AVAILABILITY_INTERVAL, - NAN_REQ_ATTR_MESH_ID_LEN, - NAN_REQ_ATTR_MESH_ID, - NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN, - NAN_REQ_ATTR_INFRASTRUCTURE_SSID, - NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES, - NAN_REQ_ATTR_FURTHER_AVAIL_VAL, - NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL, - NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS = 50, - NAN_REQ_ATTR_FURTHER_AVAIL_CHAN, - NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID, - NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP, - NAN_REQ_ATTR_PUBLISH_ID, - NAN_REQ_ATTR_PUBLISH_TTL, - NAN_REQ_ATTR_PUBLISH_PERIOD, - NAN_REQ_ATTR_PUBLISH_TYPE, - NAN_REQ_ATTR_PUBLISH_TX_TYPE, - NAN_REQ_ATTR_PUBLISH_COUNT, - NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN = 60, - NAN_REQ_ATTR_PUBLISH_SERVICE_NAME, - NAN_REQ_ATTR_PUBLISH_MATCH_ALGO, - NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN, - NAN_REQ_ATTR_PUBLISH_SERVICE_INFO, - NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER, - NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER, - NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG, - NAN_REQ_ATTR_PUBLISH_CONN_MAP = 70, - NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG, - NAN_REQ_ATTR_SUBSCRIBE_ID, - NAN_REQ_ATTR_SUBSCRIBE_TTL, - NAN_REQ_ATTR_SUBSCRIBE_PERIOD, - NAN_REQ_ATTR_SUBSCRIBE_TYPE, - NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE, - NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE, - NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER, - NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED, - NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR = 80, - NAN_REQ_ATTR_SUBSCRIBE_COUNT, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO, - NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER, - NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER, - NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG = 90, - NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP, - NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT, - NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR, - NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG, - NAN_REQ_ATTR_FOLLOWUP_ID, - NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID, - NAN_REQ_ATTR_FOLLOWUP_ADDR, - NAN_REQ_ATTR_FOLLOWUP_PRIORITY, - NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN, - NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME = 100, - NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW, - NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG, - NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL, - NAN_REQ_ATTR_DW_2G4_INTERVAL, - NAN_REQ_ATTR_DW_5G_INTERVAL, - NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL, - NAN_REQ_ATTR_PUBLISH_SDEA_LEN, - NAN_REQ_ATTR_PUBLISH_SDEA, - NAN_REQ_ATTR_RANGING_AUTO_RESPONSE, - NAN_REQ_ATTR_SDEA_PARAM_NDP_TYPE = 110, - NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG, - NAN_REQ_ATTR_SDEA_PARAM_RANGING_STATE, - NAN_REQ_ATTR_SDEA_PARAM_RANGE_REPORT, - NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG, - NAN_REQ_ATTR_RANGING_CFG_INTERVAL, - NAN_REQ_ATTR_RANGING_CFG_INDICATION, - NAN_REQ_ATTR_RANGING_CFG_INGRESS_MM, - NAN_REQ_ATTR_RANGING_CFG_EGRESS_MM, - NAN_REQ_ATTR_CIPHER_TYPE, - NAN_REQ_ATTR_SCID_LEN = 120, - NAN_REQ_ATTR_SCID, - NAN_REQ_ATTR_SECURITY_KEY_TYPE, - NAN_REQ_ATTR_SECURITY_PMK_LEN, - NAN_REQ_ATTR_SECURITY_PMK, - NAN_REQ_ATTR_SECURITY_PASSPHRASE_LEN, - NAN_REQ_ATTR_SECURITY_PASSPHRASE, - NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PUBLISH_ID, - NAN_REQ_ATTR_RANGE_RESPONSE_CFG_REQUESTOR_ID, - NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PEER_ADDR, - NAN_REQ_ATTR_RANGE_RESPONSE_CFG_RANGING_RESPONSE -}; - -enum SLSI_NAN_RESP_ATTRIBUTES { - NAN_RESP_ATTR_MAX_CONCURRENT_NAN_CLUSTERS, - NAN_RESP_ATTR_MAX_PUBLISHES, - NAN_RESP_ATTR_MAX_SUBSCRIBES, - NAN_RESP_ATTR_MAX_SERVICE_NAME_LEN, - NAN_RESP_ATTR_MAX_MATCH_FILTER_LEN, - NAN_RESP_ATTR_MAX_TOTAL_MATCH_FILTER_LEN, - NAN_RESP_ATTR_MAX_SERVICE_SPECIFIC_INFO_LEN, - NAN_RESP_ATTR_MAX_VSA_DATA_LEN, - NAN_RESP_ATTR_MAX_MESH_DATA_LEN, - NAN_RESP_ATTR_MAX_NDI_INTERFACES, - NAN_RESP_ATTR_MAX_NDP_SESSIONS, - NAN_RESP_ATTR_MAX_APP_INFO_LEN, - NAN_RESP_ATTR_SUBSCRIBE_ID, - NAN_RESP_ATTR_PUBLISH_ID -}; - -enum SLSI_NAN_EVT_ATTRIBUTES { - NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, - NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, - NAN_EVT_ATTR_MATCH_ADDR, - NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, - NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, - NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, - NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, - NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, - NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, - NAN_EVT_ATTR_MATCH_RSSI_VALUE, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED = 10, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD, - NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR, - NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR, - NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE, - NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE, - NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION = 20, - NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP, - NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID, - NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR, - NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN, - NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID, - NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN, - NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL, - NAN_EVT_ATTR_MATCH_NUM_CHANS, - NAN_EVT_ATTR_MATCH_FAMCHAN, - NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL = 30, - NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL, - NAN_EVT_ATTR_MATCH_FAM_CHANNEL, - NAN_EVT_ATTR_MATCH_FAM_MAPID, - NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP, - NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN, - NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE, - NAN_EVT_ATTR_PUBLISH_ID, - NAN_EVT_ATTR_PUBLISH_REASON, - NAN_EVT_ATTR_SUBSCRIBE_ID, - NAN_EVT_ATTR_SUBSCRIBE_REASON = 40, - NAN_EVT_ATTR_DISABLED_REASON, - NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID, - NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID, - NAN_EVT_ATTR_FOLLOWUP_ADDR, - NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, - NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, - NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, - NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, - NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, - NAN_EVT_ATTR_DISCOVERY_ENGINE_CLUSTER = 50, - NAN_EVT_ATTR_SDEA, - NAN_EVT_ATTR_SDEA_LEN, - NAN_EVT_ATTR_SCID, - NAN_EVT_ATTR_SCID_LEN, - NAN_EVT_ATTR_SDEA_PARAM_CONFIG_NAN_DATA_PATH, - NAN_EVT_ATTR_SDEA_PARAM_NDP_TYPE, - NAN_EVT_ATTR_SDEA_PARAM_SECURITY_CONFIG, - NAN_EVT_ATTR_SDEA_PARAM_RANGE_STATE, - NAN_EVT_ATTR_SDEA_PARAM_RANGE_REPORT, - NAN_EVT_ATTR_SDEA_PARAM_QOS_CFG = 60, - NAN_EVT_ATTR_RANGE_MEASUREMENT_MM, - NAN_EVT_ATTR_RANGEING_EVENT_TYPE, - NAN_EVT_ATTR_SECURITY_CIPHER_TYPE, - NAN_EVT_ATTR_STATUS -}; - -#define SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON 0X0003 -#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE 0X0004 -#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE 0X0005 -#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY 0X0006 -#define SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE 0X0007 -#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE 0X0008 -#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE 0X0009 -#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY 0X000A -#define SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT 0X000B -#define SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE 0X000C -#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4 0X000D -#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5 0X000E -#define SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE 0X000F -#define SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB 0X0010 -#define SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM 0X0011 -#define SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP 0X0012 -#define SLSI_FAPI_NAN_CONFIG_PARAM_ADDR_RANDOM_INTERVAL 0X0013 -#define SLSI_FAPI_NAN_SERVICE_NAME 0X0020 -#define SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO 0X0021 -#define SLSI_FAPI_NAN_RX_MATCH_FILTER 0X0022 -#define SLSI_FAPI_NAN_TX_MATCH_FILTER 0X0023 -#define SLSI_FAPI_NAN_SDF_MATCH_FILTER 0X0024 -#define SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE 0X0025 -#define SLSI_FAPI_NAN_INTERFACE_ADDRESS_SET 0X0026 -#define SLSI_FAPI_NAN_SDEA 0X0027 - -#define SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS 3 -#define SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN 255 -#define SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN 1024 -#define SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN 255 -#define SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42 -#define SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN 5 -#define SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN 1024 - -enum slsi_wifi_hal_nan_status_type { - /* NAN Protocol Response Codes */ - SLSI_HAL_NAN_STATUS_SUCCESS = 0, - /* NAN Discovery Engine/Host driver failures */ - SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE = 1, - /* NAN OTA failures */ - SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE = 2, - /* if the publish/subscribe id is invalid */ - SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID = 3, - /* If we run out of resources allocated */ - SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE = 4, - /* if invalid params are passed */ - SLSI_HAL_NAN_STATUS_INVALID_PARAM = 5, - /* if the requestor instance id is invalid */ - SLSI_HAL_NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID = 6, - /* if the ndp id is invalid */ - SLSI_HAL_NAN_STATUS_INVALID_NDP_ID = 7, - /* if NAN is enabled when wifi is turned off */ - SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED = 8, - /* if over the air ack is not received */ - SLSI_HAL_NAN_STATUS_NO_OTA_ACK = 9, - /* If NAN is already enabled and we are try to re-enable the same */ - SLSI_HAL_NAN_STATUS_ALREADY_ENABLED = 10, - /* If followup message internal queue is full */ - SLSI_HAL_NAN_STATUS_FOLLOWUP_QUEUE_FULL = 11, - /* Unsupported concurrency session enabled, NAN disabled notified */ - SLSI_HAL_NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12 -}; - -enum slsi_nan_status_type { - /* NAN Protocol Response Codes */ - NAN_STATUS_SUCCESS = 0, - NAN_STATUS_TIMEOUT = 1, - NAN_STATUS_DE_FAILURE = 2, - NAN_STATUS_INVALID_MSG_VERSION = 3, - NAN_STATUS_INVALID_MSG_LEN = 4, - NAN_STATUS_INVALID_MSG_ID = 5, - NAN_STATUS_INVALID_HANDLE = 6, - NAN_STATUS_NO_SPACE_AVAILABLE = 7, - NAN_STATUS_INVALID_PUBLISH_TYPE = 8, - NAN_STATUS_INVALID_TX_TYPE = 9, - NAN_STATUS_INVALID_MATCH_ALGORITHM = 10, - NAN_STATUS_DISABLE_IN_PROGRESS = 11, - NAN_STATUS_INVALID_TLV_LEN = 12, - NAN_STATUS_INVALID_TLV_TYPE = 13, - NAN_STATUS_MISSING_TLV_TYPE = 14, - NAN_STATUS_INVALID_TOTAL_TLVS_LEN = 15, - NAN_STATUS_INVALID_MATCH_HANDLE = 16, - NAN_STATUS_INVALID_TLV_VALUE = 17, - NAN_STATUS_INVALID_TX_PRIORITY = 18, - NAN_STATUS_INVALID_CONNECTION_MAP = 19, - NAN_STATUS_INVALID_TCA_ID = 20, - NAN_STATUS_INVALID_STATS_ID = 21, - NAN_STATUS_NAN_NOT_ALLOWED = 22, - NAN_STATUS_NO_OTA_ACK = 23, - NAN_STATUS_TX_FAIL = 24, - /* 25-4095 Reserved */ - /* NAN Configuration Response codes */ - NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096, - NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097, - NAN_STATUS_INVALID_HOP_COUNT_LIMIT = 4098, - NAN_STATUS_INVALID_MASTER_PREFERENCE_VALUE = 4099, - NAN_STATUS_INVALID_LOW_CLUSTER_ID_VALUE = 4100, - NAN_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE = 4101, - NAN_STATUS_INVALID_BACKGROUND_SCAN_PERIOD = 4102, - NAN_STATUS_INVALID_RSSI_PROXIMITY_VALUE = 4103, - NAN_STATUS_INVALID_SCAN_CHANNEL = 4104, - NAN_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP = 4105, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_NUMCHAN_VALUE = 4106, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_DURATION_VALUE = 4107, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CLASS_VALUE = 4108, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CHANNEL_VALUE = 4109, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE = 4110, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_MAP_ID = 4111, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE = 4112, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE = 4113, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE = 4114, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE = 4115, - NAN_STATUS_MISSING_FUTHER_AVAILABILITY_MAP = 4116, - NAN_STATUS_INVALID_BAND_CONFIG_FLAGS = 4117, - NAN_STATUS_INVALID_RANDOM_FACTOR_UPDATE_TIME_VALUE = 4118, - NAN_STATUS_INVALID_ONGOING_SCAN_PERIOD = 4119, - NAN_STATUS_INVALID_DW_INTERVAL_VALUE = 4120, - NAN_STATUS_INVALID_DB_INTERVAL_VALUE = 4121, - /* 4122-8191 RESERVED */ - NAN_TERMINATED_REASON_INVALID = 8192, - NAN_TERMINATED_REASON_TIMEOUT = 8193, - NAN_TERMINATED_REASON_USER_REQUEST = 8194, - NAN_TERMINATED_REASON_FAILURE = 8195, - NAN_TERMINATED_REASON_COUNT_REACHED = 8196, - NAN_TERMINATED_REASON_DE_SHUTDOWN = 8197, - NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198, - NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199, - NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200, - NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201 -}; - -enum slsi_nan_response_type { - NAN_RESPONSE_ENABLED = 0, - NAN_RESPONSE_DISABLED = 1, - NAN_RESPONSE_PUBLISH = 2, - NAN_RESPONSE_PUBLISH_CANCEL = 3, - NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4, - NAN_RESPONSE_SUBSCRIBE = 5, - NAN_RESPONSE_SUBSCRIBE_CANCEL = 6, - NAN_RESPONSE_STATS = 7, - NAN_RESPONSE_CONFIG = 8, - NAN_RESPONSE_TCA = 9, - NAN_RESPONSE_ERROR = 10, - NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11, - NAN_RESPONSE_GET_CAPABILITIES = 12 -}; - -enum slsi_nan_disc_event_type { - NAN_EVENT_ID_DISC_MAC_ADDR = 0, - NAN_EVENT_ID_STARTED_CLUSTER, - NAN_EVENT_ID_JOINED_CLUSTER -}; - -struct slsi_hal_nan_social_channel_scan_params { - u8 dwell_time[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS]; - u16 scan_period[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS]; -}; - -struct slsi_hal_nan_connectivity_capability { - u8 payload_transmit_flag; - u8 is_wfd_supported; - u8 is_wfds_supported; - u8 is_tdls_supported; - u8 is_ibss_supported; - u8 is_mesh_supported; - u8 wlan_infra_field; -}; - -struct slsi_hal_nan_post_discovery_param { - u8 type; /* NanConnectionType */ - u8 role; /* NanDeviceRole */ - u8 transmit_freq; - u8 duration; /* NanAvailDuration */ - u32 avail_interval_bitmap; - u8 addr[ETH_ALEN]; - u16 mesh_id_len; - u8 mesh_id[32]; - u16 infrastructure_ssid_len; - u8 infrastructure_ssid_val[32]; -}; - -struct slsi_hal_nan_further_availability_channel { - /* struct slsi_hal_nan_further_availability_channel*/ - u8 entry_control; - u8 class_val; - u8 channel; - u8 mapid; - u32 avail_interval_bitmap; -}; - -struct slsi_hal_nan_further_availability_map { - u8 numchans; - struct slsi_hal_nan_further_availability_channel famchan[32]; -}; - -struct slsi_hal_nan_receive_post_discovery { - u8 type; - u8 role; - u8 duration; - u32 avail_interval_bitmap; - u8 mapid; - u8 addr[ETH_ALEN]; - u16 mesh_id_len; - u8 mesh_id[32]; - u16 infrastructure_ssid_len; - u8 infrastructure_ssid_val[32]; -}; - -struct slsi_nan_sdea_ctrl_params { - u8 config_nan_data_path; - u8 ndp_type; - u8 security_cfg; - u8 ranging_state; - u8 range_report; - u8 qos_cfg; -}; - -struct slsi_nan_ranging_cfg { - u32 ranging_interval_msec; - u32 config_ranging_indications; - u32 distance_ingress_mm; - u32 distance_egress_mm; -}; - -struct slsi_nan_range_response_cfg { - u16 publish_id; - u32 requestor_instance_id; - u8 peer_addr[ETH_ALEN]; - u8 ranging_response; -}; - -#define SLSI_NAN_PMK_INFO_LEN 32 -#define SLSI_NAN_SECURITY_MAX_PASSPHRASE_LEN 63 -#define SLSI_NAN_MAX_SCID_BUF_LEN 1024 -struct slsi_nan_security_pmk { - u32 pmk_len; - u8 pmk[SLSI_NAN_PMK_INFO_LEN]; -}; - -struct slsi_nan_security_passphrase { - u32 passphrase_len; - u8 passphrase[SLSI_NAN_SECURITY_MAX_PASSPHRASE_LEN]; -}; - -struct slsi_nan_security_key_info { - u8 key_type; - union { - struct slsi_nan_security_pmk pmk_info; - struct slsi_nan_security_passphrase passphrase_info; - } body; -}; - -struct slsi_nan_security_info { - u32 cipher_type; - u32 scid_len; - u8 scid[SLSI_NAN_MAX_SCID_BUF_LEN]; - struct slsi_nan_security_key_info key_info; -}; - -struct slsi_hal_nan_enable_req { - /* Mandatory parameters below */ - u8 master_pref; - u16 cluster_low; - u16 cluster_high; - - u8 config_support_5g; - u8 support_5g_val; - u8 config_sid_beacon; - u8 sid_beacon_val; - u8 config_2dot4g_rssi_close; - u8 rssi_close_2dot4g_val; - - u8 config_2dot4g_rssi_middle; - u8 rssi_middle_2dot4g_val; - - u8 config_2dot4g_rssi_proximity; - u8 rssi_proximity_2dot4g_val; - - u8 config_hop_count_limit; - u8 hop_count_limit_val; - - u8 config_2dot4g_support; - u8 support_2dot4g_val; - - u8 config_2dot4g_beacons; - u8 beacon_2dot4g_val; - u8 config_2dot4g_sdf; - u8 sdf_2dot4g_val; - u8 config_5g_beacons; - u8 beacon_5g_val; - u8 config_5g_sdf; - u8 sdf_5g_val; - u8 config_5g_rssi_close; - u8 rssi_close_5g_val; - u8 config_5g_rssi_middle; - u8 rssi_middle_5g_val; - u8 config_5g_rssi_close_proximity; - u8 rssi_close_proximity_5g_val; - u8 config_rssi_window_size; - u8 rssi_window_size_val; - /* The 24 bit Organizationally Unique ID + the 8 bit Network Id. */ - u8 config_oui; - u32 oui_val; - u8 config_intf_addr; - u8 intf_addr_val[ETH_ALEN]; - - u8 config_cluster_attribute_val; - u8 config_scan_params; - struct slsi_hal_nan_social_channel_scan_params scan_params_val; - u8 config_random_factor_force; - u8 random_factor_force_val; - u8 config_hop_count_force; - u8 hop_count_force_val; - - /* channel frequency in MHz to enable Nan on */ - u8 config_24g_channel; - u32 channel_24g_val; - - u8 config_5g_channel; - int channel_5g_val; - u8 config_subscribe_sid_beacon; - u32 subscribe_sid_beacon_val; - - /*NanConfigDW config_dw*/ - u8 config_2dot4g_dw_band; - u32 dw_2dot4g_interval_val; - u8 config_5g_dw_band; - u32 dw_5g_interval_val; - u32 disc_mac_addr_rand_interval_sec; -}; - -struct slsi_hal_nan_publish_req { - /* id 0 means new publish, any other id is existing publish */ - u16 publish_id; - /* how many seconds to run for. 0 means forever until canceled */ - u16 ttl; - /* periodicity of OTA unsolicited publish. - * Specified in increments of 500 ms - */ - u16 period; - u8 publish_type;/* 0= unsolicited, solicited = 1, 2= both */ - u8 tx_type; /* 0 = broadcast, 1= unicast if solicited publish */ - /* number of OTA Publish, 0 means forever until canceled */ - u8 publish_count; - u16 service_name_len; - u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN]; - u8 publish_match_indicator; - - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - - u16 rx_match_filter_len; - u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - - u16 tx_match_filter_len; - u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - - u8 rssi_threshold_flag; - - /* 8-bit bitmap which allows the Host to associate this publish - * with a particular Post-NAN Connectivity attribute - * which has been sent down in a NanConfigureRequest/NanEnableRequest - * message. If the DE fails to find a configured Post-NAN - * connectivity attributes referenced by the bitmap, - * the DE will return an error code to the Host. - * If the Publish is configured to use a Post-NAN Connectivity - * attribute and the Host does not refresh the Post-NAN Connectivity - * attribute the Publish will be canceled and the Host will be sent - * a PublishTerminatedIndication message. - */ - u8 connmap; - /* Set/Enable corresponding bits to disable any - * indications that follow a publish. - * BIT0 - Disable publish termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - u8 recv_indication_cfg; - - u8 service_responder_policy; - struct slsi_nan_security_info sec_info; - struct slsi_nan_sdea_ctrl_params sdea_params; - struct slsi_nan_ranging_cfg ranging_cfg; - u8 ranging_auto_response; - struct slsi_nan_range_response_cfg range_response_cfg; - - u16 sdea_service_specific_info_len; - u8 sdea_service_specific_info[SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN]; -}; - -struct slsi_hal_nan_subscribe_req { - /* id 0 means new subscribe, non zero is existing subscribe */ - u16 subscribe_id; - /* how many seconds to run for. 0 means forever until canceled */ - u16 ttl; - /* periodicity of OTA Active Subscribe. Units in increments - * of 500 ms , 0 = attempt every DW - */ - u16 period; - - /* Flag which specifies how the Subscribe request shall be processed. */ - u8 subscribe_type; /* 0 - PASSIVE , 1- ACTIVE */ - - /* Flag which specifies on Active Subscribes how the Service Response - * Filter attribute is populated. - */ - u8 service_response_filter; /* 0 - Bloom Filter, 1 - MAC Addr */ - - /* Flag which specifies how the Service Response Filter Include - * bit is populated. - * 0=Do not respond if in the Address Set, 1= Respond - */ - u8 service_response_include; - - /* Flag which specifies if the Service Response Filter - * should be used when creating Subscribes. - * 0=Do not send the Service Response Filter,1= send - */ - u8 use_service_response_filter; - - /* Flag which specifies if the Service Specific Info is needed in - * the Publish message before creating the MatchIndication - */ - u8 ssi_required_for_match_indication; /* 0=Not needed, 1= Required */ - - /* Field which specifies how matching indication to host is controlled. - * 0 - Match and Indicate Once - * 1 - Match and Indicate continuous - * 2 - Match and Indicate never. This means don't - * indicate match to host. - * 3 - Reserved - */ - u8 subscribe_match_indicator; - - /* The number of Subscribe Matches which should occur - * before the Subscribe request is automatically terminated. - */ - /* If this value is 0 this field is not used by DE.*/ - u8 subscribe_count; - - /* length of service name */ - /* UTF-8 encoded string identifying the service */ - u16 service_name_len; - u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN]; - - /* Sequence of values which further specify the published service - * beyond the service name - */ - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - - /* Ordered sequence of pairs used to filter out - * received publish discovery messages. - * This can be sent both for a Passive or an Active Subscribe - */ - u16 rx_match_filter_len; - u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - - /* Ordered sequence of pairs included in the - * Discovery Frame when an Active Subscribe is used. - */ - u16 tx_match_filter_len; - u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - u8 rssi_threshold_flag; - - u8 connmap; - /* NAN Interface Address, conforming to the format as described in - * 8.2.4.3.2 of IEEE Std. 802.11-2012. - */ - u8 num_intf_addr_present; - u8 intf_addr[SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS][ETH_ALEN]; - /* Set/Enable corresponding bits to disable - * indications that follow a subscribe. - * BIT0 - Disable subscribe termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - u8 recv_indication_cfg; - - struct slsi_nan_security_info sec_info; - struct slsi_nan_sdea_ctrl_params sdea_params; - struct slsi_nan_ranging_cfg ranging_cfg; - u8 ranging_auto_response; - struct slsi_nan_range_response_cfg range_response_cfg; - - u16 sdea_service_specific_info_len; - u8 sdea_service_specific_info[SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN]; -}; - -struct slsi_hal_nan_transmit_followup_req { - /* Publish or Subscribe Id of an earlier Publish/Subscribe */ - u16 publish_subscribe_id; - - /* This Id is the Requestor Instance that is passed as - * part of earlier MatchInd/FollowupInd message. - */ - u32 requestor_instance_id; - u8 addr[ETH_ALEN]; /* Unicast address */ - u8 priority; /* priority of the request 2=high */ - u8 dw_or_faw; /* 0= send in a DW, 1=send in FAW */ - - /* Sequence of values which further specify the published service beyond - * the service name. - */ - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - /* Set/Enable corresponding bits to disable - * responses after followUp. - * BIT0 - Disable followUp response from FW. - */ - u8 recv_indication_cfg; - - u16 sdea_service_specific_info_len; - u8 sdea_service_specific_info[SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN]; -}; - -struct slsi_hal_nan_config_req { - u8 config_sid_beacon; - u8 sid_beacon; - u8 config_rssi_proximity; - u8 rssi_proximity; - u8 config_master_pref; - u8 master_pref; - /* 1 byte value which defines the RSSI filter threshold. - * Any Service Descriptors received above this value - * that are configured for RSSI filtering will be dropped. - * The rssi values should be specified without sign. - * For eg: -70dBm should be specified as 70. - */ - u8 config_5g_rssi_close_proximity; - u8 rssi_close_proximity_5g_val; - u8 config_rssi_window_size; - u16 rssi_window_size_val; - /* If set to 1, the Discovery Engine will enclose the Cluster - * Attribute only sent in Beacons in a Vendor Specific Attribute - * and transmit in a Service Descriptor Frame. - */ - u8 config_cluster_attribute_val; - u8 config_scan_params; - struct slsi_hal_nan_social_channel_scan_params scan_params_val; - /* 1 byte quantity which forces the Random Factor to a particular - * value for all transmitted Sync/Discovery beacons - */ - u8 config_random_factor_force; - u8 random_factor_force_val; - /* 1 byte quantity which forces the HC for all transmitted Sync and - * Discovery Beacon NO matter the real HC being received over the - * air. - */ - u8 config_hop_count_force; - u8 hop_count_force_val; - /* NAN Post Connectivity Capability */ - u8 config_conn_capability; - struct slsi_hal_nan_connectivity_capability conn_capability_val; - /* NAN Post Discover Capability */ - u8 num_config_discovery_attr; - struct slsi_hal_nan_post_discovery_param discovery_attr_val[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN]; - /* NAN Further availability Map */ - u8 config_fam; - struct slsi_hal_nan_further_availability_map fam_val; - - int channel_5g_val; - u8 config_subscribe_sid_beacon; - u32 subscribe_sid_beacon_val; - - /*NanConfigDW config_dw*/ - u8 config_2dot4g_dw_band; - u32 dw_2dot4g_interval_val; - u8 config_5g_dw_band; - u32 dw_5g_interval_val; - u32 disc_mac_addr_rand_interval_sec; - -}; - -struct slsi_hal_nan_capabilities { - u32 max_concurrent_nan_clusters; - u32 max_publishes; - u32 max_subscribes; - u32 max_service_name_len; - u32 max_match_filter_len; - u32 max_total_match_filter_len; - u32 max_service_specific_info_len; - u32 max_vsa_data_len; - u32 max_mesh_data_len; - u32 max_ndi_interfaces; - u32 max_ndp_sessions; - u32 max_app_info_len; -}; - -struct slsi_hal_nan_followup_ind { - u16 publish_subscribe_id; - u32 requestor_instance_id; - u8 addr[ETH_ALEN]; - u8 dw_or_faw; - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - u16 sdea_service_specific_info_len; - u8 sdea_service_specific_info[SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN]; -}; - -struct slsi_hal_nan_match_ind { - u16 publish_subscribe_id; - u32 requestor_instance_id; - u8 addr[ETH_ALEN]; - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - u16 sdf_match_filter_len; - u8 sdf_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - u8 match_occurred_flag; - u8 out_of_resource_flag; - u8 rssi_value; - u8 is_conn_capability_valid; - struct slsi_hal_nan_connectivity_capability conn_capability; - u8 num_rx_discovery_attr; - struct slsi_hal_nan_receive_post_discovery discovery_attr[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN]; - u8 num_chans; - struct slsi_hal_nan_further_availability_channel famchan[32]; - u8 cluster_attribute_len; - u8 cluster_attribute[32]; - struct slsi_nan_security_info sec_info; - struct slsi_nan_sdea_ctrl_params peer_sdea_params; - u32 range_measurement_mm; - u32 ranging_event_type; - u16 sdea_service_specific_info_len; - u8 sdea_service_specific_info[SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN]; -}; - -void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr); -struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev); -int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, - const void *data, int len); -int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); -#endif diff --git a/drivers/net/wireless/scsc/porting_imx.h b/drivers/net/wireless/scsc/porting_imx.h deleted file mode 100644 index ac9765a65eeb..000000000000 --- a/drivers/net/wireless/scsc/porting_imx.h +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/**/ - -#ifndef _PORTING_IMX__H__ -#define _PORTING_IMX__H__ -#endif -/** - * ether_addr_copy - Copy an Ethernet address - * @dst: Pointer to a six-byte array Ethernet address destination - * @src: Pointer to a six-byte array Ethernet address source - * - * Please note: dst & src must both be aligned to u16. - */ -static inline void ether_addr_copy(u8 *dst, const u8 *src) -{ -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) - *(u32 *)dst = *(const u32 *)src; - *(u16 *)(dst + 4) = *(const u16 *)(src + 4); -#else - u16 *a = (u16 *)dst; - const u16 *b = (const u16 *)src; - - a[0] = b[0]; - a[1] = b[1]; - a[2] = b[2]; -#endif -} - -static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec) -{ - return ktime_add_ns(kt, msec * NSEC_PER_MSEC); -} - - diff --git a/drivers/net/wireless/scsc/procfs.c b/drivers/net/wireless/scsc/procfs.c deleted file mode 100755 index 738141f31e3a..000000000000 --- a/drivers/net/wireless/scsc/procfs.c +++ /dev/null @@ -1,1204 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "dev.h" -#include "procfs.h" -#include "debug.h" -#include "mlme.h" -#include "mgt.h" -#include "mib.h" -#include "cac.h" -#include "hip.h" -#include "netif.h" -#include "ioctl.h" -#include "nl80211_vendor.h" - -#include "mib.h" - -int slsi_procfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = SLSI_PDE_DATA(inode); - return 0; -} - -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG -static int slsi_printf_mutex_stats(char *buf, const size_t bufsz, const char *printf_padding, struct slsi_mutex *mutex_p) -{ - int pos = 0; - const char *filename; - bool is_locked; - - if (mutex_p->valid) { - is_locked = SLSI_MUTEX_IS_LOCKED(*mutex_p); - pos += scnprintf(buf, bufsz, "INFO: lock:%d\n", is_locked); - if (is_locked) { - filename = strrchr(mutex_p->file_name_before, '/'); - if (filename) - filename++; - else - filename = mutex_p->file_name_before; - pos += scnprintf(buf + pos, bufsz - pos, "\t%sTryingToAcquire:%s:%d\n", printf_padding, - filename, mutex_p->line_no_before); - filename = strrchr(mutex_p->file_name_after, '/'); - if (filename) - filename++; - else - filename = mutex_p->file_name_after; - pos += scnprintf(buf + pos, bufsz - pos, "\t%sAcquired:%s:%d:%s\n", printf_padding, - filename, mutex_p->line_no_after, mutex_p->function); - pos += scnprintf(buf + pos, bufsz - pos, "\t%sProcessName:%s\n", printf_padding, mutex_p->owner->comm); - } - } else { - pos += scnprintf(buf, bufsz, "NoInit\n"); - } - return pos; -} - -static ssize_t slsi_procfs_mutex_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[76 + (200 * CONFIG_SCSC_WLAN_MAX_INTERFACES)]; - int pos = 0; - int i; - const size_t bufsz = sizeof(buf); - struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - struct net_device *dev; - struct netdev_vif *ndev_vif; - - SLSI_UNUSED_PARAMETER(file); - - pos += scnprintf(buf, bufsz, "sdev\n"); - pos += scnprintf(buf + pos, bufsz - pos, "\tnetdev_add_remove_mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t", &sdev->netdev_add_remove_mutex); - pos += scnprintf(buf + pos, bufsz - pos, "\tstart_stop_mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t", &sdev->start_stop_mutex); - pos += scnprintf(buf + pos, bufsz - pos, "\tdevice_config_mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t", &sdev->device_config_mutex); - pos += scnprintf(buf + pos, bufsz - pos, "\tsig_wait.mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t", &sdev->sig_wait.mutex); -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING - pos += scnprintf(buf + pos, bufsz - pos, "\tlogger_mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t", &sdev->logger_mutex); -#endif - - for (i = 1; i < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; i++) { - pos += scnprintf(buf + pos, bufsz - pos, "netdevvif %d\n", i); - dev = slsi_get_netdev_locked(sdev, i); - if (!dev) - continue; - ndev_vif = netdev_priv(dev); - if (ndev_vif->is_available) { - pos += scnprintf(buf + pos, bufsz - pos, "\tvif_mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t\t", &ndev_vif->vif_mutex); - pos += scnprintf(buf + pos, bufsz - pos, "\tsig_wait.mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t\t", &ndev_vif->sig_wait.mutex); - pos += scnprintf(buf + pos, bufsz - pos, "\tscan_mutex "); - pos += slsi_printf_mutex_stats(buf + pos, bufsz - pos, "\t\t", &ndev_vif->scan_mutex); - } else { - pos += scnprintf(buf + pos, bufsz - pos, "\tvif UNAVAILABLE\n"); - } - } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} -#endif - -static ssize_t slsi_procfs_throughput_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[5 * 25]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - struct net_device *dev; - struct netdev_vif *ndev_vif; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_value *values = NULL; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 3, 0 } }, - { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 4, 0 } }, - { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 5, 0 } }, - { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 25, 0 } }, - { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 30, 0 } } }; - - SLSI_UNUSED_PARAMETER(file); - - dev = slsi_get_netdev(sdev, 1); - ndev_vif = netdev_priv(dev); - - if (ndev_vif->activated) { - mibrsp.dataLength = 15 * ARRAY_SIZE(get_values); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - values = slsi_read_mibs(sdev, dev, get_values, ARRAY_SIZE(get_values), &mibrsp); - if (!values) { - kfree(mibrsp.data); - return -EINVAL; - } - if (values[0].type != SLSI_MIB_TYPE_UINT) - SLSI_ERR(sdev, "invalid type. iter:%d", 0); /*bad_fcs_count*/ - if (values[1].type != SLSI_MIB_TYPE_UINT) - SLSI_ERR(sdev, "invalid type. iter:%d", 1); /*missed_ba_count*/ - if (values[2].type != SLSI_MIB_TYPE_UINT) - SLSI_ERR(sdev, "invalid type. iter:%d", 2); /*missed_ack_count*/ - if (values[3].type != SLSI_MIB_TYPE_UINT) - SLSI_ERR(sdev, "invalid type. iter:%d", 3); /*mac_bad_sig_count*/ - if (values[4].type != SLSI_MIB_TYPE_UINT) - SLSI_ERR(sdev, "invalid type. iter:%d", 4); /*rx_error_count*/ - - pos += scnprintf(buf, bufsz, "RX FCS: %d\n", values[0].u.uintValue); - pos += scnprintf(buf + pos, bufsz - pos, "RX bad SIG: %d\n", values[3].u.uintValue); - pos += scnprintf(buf + pos, bufsz - pos, "RX dot11 error: %d\n", values[4].u.uintValue); - pos += scnprintf(buf + pos, bufsz - pos, "TX MPDU no ACK: %d\n", values[2].u.uintValue); - pos += scnprintf(buf + pos, bufsz - pos, "TX A-MPDU no ACK: %d\n", values[1].u.uintValue); - - kfree(values); - kfree(mibrsp.data); - } else { - pos += scnprintf(buf, bufsz, "RX FCS: %d\n", 0); - pos += scnprintf(buf + pos, bufsz - pos, "RX bad SIG: %d\n", 0); - pos += scnprintf(buf + pos, bufsz - pos, "RX dot11 error: %d\n", 0); - pos += scnprintf(buf + pos, bufsz - pos, "TX MPDU no ACK: %d\n", 0); - pos += scnprintf(buf + pos, bufsz - pos, "TX A-MPDU no ACK: %d\n", 0); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t slsi_procfs_sta_bss_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[100]; - int pos; - const size_t bufsz = sizeof(buf); - struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - struct net_device *dev; - struct netdev_vif *ndev_vif; - struct cfg80211_bss *sta_bss; - int channel = 0, center_freq = 0; - u8 no_mac[] = {0, 0, 0, 0, 0, 0}; - u8 *mac_ptr; - u8 ssid[33]; - s32 signal = 0; - - SLSI_UNUSED_PARAMETER(file); - - mac_ptr = no_mac; - ssid[0] = 0; - - dev = slsi_get_netdev(sdev, 1); - if (!dev) - goto exit; - - ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - sta_bss = ndev_vif->sta.sta_bss; - if (sta_bss && ndev_vif->vif_type == FAPI_VIFTYPE_STATION && - ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED) { - const u8 *ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, sta_bss->ies->data, sta_bss->ies->len); - - if (ssid_ie) { - memcpy(ssid, &ssid_ie[2], ssid_ie[1]); - ssid[ssid_ie[1]] = 0; - } - - if (sta_bss->channel) { - channel = sta_bss->channel->hw_value; - center_freq = sta_bss->channel->center_freq; - } - mac_ptr = sta_bss->bssid; - signal = sta_bss->signal; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - -exit: - pos = scnprintf(buf, bufsz, "%pM,%s,%d,%d,%d", mac_ptr, ssid, channel, center_freq, signal); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t slsi_procfs_big_data_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[100]; - int pos; - const size_t bufsz = sizeof(buf); - struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - struct net_device *dev; - struct netdev_vif *ndev_vif; - - SLSI_UNUSED_PARAMETER(file); - dev = slsi_get_netdev(sdev, 1); - if (!dev) - goto exit; - - ndev_vif = netdev_priv(dev); - -exit: - pos = slsi_get_sta_info(dev, buf, bufsz); - if (pos >= 0) - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return 0; -} - -static int slsi_procfs_status_show(struct seq_file *m, void *v) -{ - struct slsi_dev *sdev = (struct slsi_dev *)m->private; - const char *state; - u32 conf_hip4_ver = 0; - int i; - - SLSI_UNUSED_PARAMETER(v); - - switch (sdev->device_state) { - case SLSI_DEVICE_STATE_ATTACHING: - state = "Attaching"; - break; - case SLSI_DEVICE_STATE_STOPPED: - state = "Stopped"; - break; - case SLSI_DEVICE_STATE_STARTING: - state = "Starting"; - break; - case SLSI_DEVICE_STATE_STARTED: - state = "Started"; - break; - case SLSI_DEVICE_STATE_STOPPING: - state = "Stopping"; - break; - default: - state = "UNKNOWN"; - break; - } - - seq_printf(m, "Driver FAPI Version: MA SAP : %d.%d.%d\n", FAPI_MAJOR_VERSION(FAPI_DATA_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_DATA_SAP_VERSION), FAPI_DATA_SAP_ENG_VERSION); - seq_printf(m, "Driver FAPI Version: MLME SAP : %d.%d.%d\n", FAPI_MAJOR_VERSION(FAPI_CONTROL_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_CONTROL_SAP_VERSION), FAPI_CONTROL_SAP_ENG_VERSION); - seq_printf(m, "Driver FAPI Version: DEBUG SAP : %d.%d.%d\n", FAPI_MAJOR_VERSION(FAPI_DEBUG_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_DEBUG_SAP_VERSION), FAPI_DEBUG_SAP_ENG_VERSION); - seq_printf(m, "Driver FAPI Version: TEST SAP : %d.%d.%d\n", FAPI_MAJOR_VERSION(FAPI_TEST_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_TEST_SAP_VERSION), FAPI_TEST_SAP_ENG_VERSION); - - if (atomic_read(&sdev->hip.hip_state) == SLSI_HIP_STATE_STARTED) { - conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); - seq_printf(m, "HIP4 Version : %d\n", conf_hip4_ver); - if (conf_hip4_ver == 4) { - seq_printf(m, "Chip FAPI Version (v4): MA SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_ma_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_ma_ver))); - seq_printf(m, "Chip FAPI Version (v4): MLME SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_mlme_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_mlme_ver))); - seq_printf(m, "Chip FAPI Version (v4): DEBUG SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_debug_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_debug_ver))); - seq_printf(m, "Chip FAPI Version (v4): TEST SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_test_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_test_ver))); - } else if (conf_hip4_ver == 5) { - seq_printf(m, "Chip FAPI Version (v5): MA SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_ma_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_ma_ver))); - seq_printf(m, "Chip FAPI Version (v5): MLME SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_mlme_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_mlme_ver))); - seq_printf(m, "Chip FAPI Version (v5): DEBUG SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_debug_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_debug_ver))); - seq_printf(m, "Chip FAPI Version (v5): TEST SAP : %d.%d\n", - FAPI_MAJOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_test_ver)), - FAPI_MINOR_VERSION(scsc_wifi_get_hip_config_version_5_u16(&sdev->hip4_inst.hip_control->config_v5, sap_test_ver))); - } - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - seq_puts(m, "Driver Debug : Enabled\n"); -#else - seq_puts(m, "Driver Debug : Disabled\n"); -#endif - seq_printf(m, "Driver State : %s\n", state); - - seq_printf(m, "HW Version [MIB] : 0x%.4X (%u)\n", sdev->chip_info_mib.chip_version, sdev->chip_info_mib.chip_version); - seq_printf(m, "Platform Build [MIB] : 0x%.4X (%u)\n", sdev->plat_info_mib.plat_build, sdev->plat_info_mib.plat_build); - for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++) { - seq_printf(m, "Hash [MIB%2d] : 0x%.4X (%u)\n", i, sdev->mib[i].mib_hash, sdev->mib[i].mib_hash); - seq_printf(m, "Platform: [MIB%2d] : %s\n", i, sdev->mib[i].platform); - } - seq_printf(m, "Hash [local_MIB] : 0x%.4X (%u)\n", sdev->local_mib.mib_hash, sdev->local_mib.mib_hash); - seq_printf(m, "Platform: [local_MIB] : %s\n", sdev->local_mib.platform); - - return 0; -} - -static int slsi_procfs_build_show(struct seq_file *m, void *v) -{ - SLSI_UNUSED_PARAMETER(v); - seq_printf(m, "FAPI_DATA_SAP_VERSION : %d.%d.%d\n", - FAPI_MAJOR_VERSION(FAPI_DATA_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_DATA_SAP_VERSION), - FAPI_DATA_SAP_ENG_VERSION); - seq_printf(m, "FAPI_CONTROL_SAP_VERSION : %d.%d.%d\n", - FAPI_MAJOR_VERSION(FAPI_CONTROL_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_CONTROL_SAP_VERSION), - FAPI_CONTROL_SAP_ENG_VERSION); - seq_printf(m, "FAPI_DEBUG_SAP_VERSION : %d.%d.%d\n", - FAPI_MAJOR_VERSION(FAPI_DEBUG_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_DEBUG_SAP_VERSION), - FAPI_DEBUG_SAP_ENG_VERSION); - seq_printf(m, "FAPI_TEST_SAP_VERSION : %d.%d.%d\n", - FAPI_MAJOR_VERSION(FAPI_TEST_SAP_VERSION), - FAPI_MINOR_VERSION(FAPI_TEST_SAP_VERSION), - FAPI_TEST_SAP_ENG_VERSION); - seq_printf(m, "CONFIG_SCSC_WLAN_MAX_INTERFACES : %d\n", CONFIG_SCSC_WLAN_MAX_INTERFACES); -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - seq_puts(m, "CONFIG_SCSC_WLAN_RX_NAPI : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_RX_NAPI : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_RX_NAPI_GRO - seq_puts(m, "CONFIG_SCSC_WLAN_RX_NAPI_GRO : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_RX_NAPI_GRO : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_ANDROID - seq_puts(m, "CONFIG_SCSC_WLAN_ANDROID : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_ANDROID : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - seq_puts(m, "CONFIG_SCSC_WLAN_GSCAN_ENABLE : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_GSCAN_ENABLE : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD - seq_puts(m, "CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_PRIORITISE_IMP_FRAMES - seq_puts(m, "CONFIG_SCSC_WLAN_PRIORITISE_IMP_FRAMES : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_PRIORITISE_IMP_FRAMES : n\n"); -#endif - seq_puts(m, "-------------------------------------------------\n"); -#ifdef CONFIG_SCSC_WLAN_DEBUG - seq_puts(m, "CONFIG_SCSC_WLAN_DEBUG : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_DEBUG : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_SKB_TRACKING - seq_puts(m, "CONFIG_SCSC_WLAN_SKB_TRACKING : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_SKB_TRACKING : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - seq_puts(m, "CONFIG_SCSC_WLAN_MUTEX_DEBUG : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_MUTEX_DEBUG : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING - seq_puts(m, "CONFIG_SCSC_WLAN_ENHANCED_LOGGING : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_ENHANCED_LOGGING : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - seq_puts(m, "CONFIG_SCSC_WLAN_WIFI_SHARING : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_WIFI_SHARING : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_SINGLE_ANTENNA - seq_puts(m, "CONFIG_SCSC_WLAN_SINGLE_ANTENNA : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_SINGLE_ANTENNA : n\n"); -#endif -#ifdef CONFIG_SCSC_AP_INTERFACE_NAME - seq_printf(m, "CONFIG_SCSC_AP_INTERFACE_NAME : %s\n", CONFIG_SCSC_AP_INTERFACE_NAME); -#endif -#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE - seq_puts(m, "CONFIG_SCSC_WIFI_NAN_ENABLE : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WIFI_NAN_ENABLE : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA - seq_puts(m, "CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA : n\n"); -#endif -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - seq_puts(m, "CONFIG_SLSI_WLAN_STA_FWD_BEACON : y\n"); -#else - seq_puts(m, "CONFIG_SLSI_WLAN_STA_FWD_BEACON : n\n"); -#endif -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - seq_puts(m, "CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT : y\n"); -#else - seq_puts(m, "CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT : n\n"); -#endif - - return 0; -} - -static const char *slsi_procfs_vif_type_to_str(u16 type) -{ - switch (type) { - case FAPI_VIFTYPE_STATION: - return "STATION"; - case FAPI_VIFTYPE_AP: - return "AP"; - case FAPI_VIFTYPE_UNSYNCHRONISED: - return "UNSYNCH"; - default: - return "?"; - } -} - -static int slsi_procfs_vifs_show(struct seq_file *m, void *v) -{ - struct slsi_dev *sdev = (struct slsi_dev *)m->private; - u16 vif; - u16 peer_index; - - SLSI_UNUSED_PARAMETER(v); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (vif = 1; vif <= CONFIG_SCSC_WLAN_MAX_INTERFACES; vif++) { - struct net_device *dev = slsi_get_netdev_locked(sdev, vif); - struct netdev_vif *ndev_vif; - - if (!dev) - continue; - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - continue; - } - seq_printf(m, "vif:%d %pM %s\n", vif, dev->dev_addr, slsi_procfs_vif_type_to_str(ndev_vif->vif_type)); - for (peer_index = 0; peer_index < SLSI_ADHOC_PEER_CONNECTIONS_MAX; peer_index++) { - struct slsi_peer *peer = ndev_vif->peer_sta_record[peer_index]; - - if (peer && peer->valid) - seq_printf(m, "vif:%d %pM peer[%d] %pM\n", vif, dev->dev_addr, peer_index, peer->address); - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - return 0; -} - -static ssize_t slsi_procfs_read_int(struct file *file, char __user *user_buf, size_t count, loff_t *ppos, int value, const char *extra) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - SLSI_UNUSED_PARAMETER(file); - - pos += scnprintf(buf + pos, bufsz - pos, "%d\n", value); - if (extra) - pos += scnprintf(buf + pos, bufsz - pos, "%s", extra); - SLSI_INFO((struct slsi_dev *)file->private_data, "%s", buf); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t slsi_procfs_uapsd_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = file->private_data; - struct net_device *dev = NULL; - struct netdev_vif *ndev_vif = NULL; - int qos_info = 0; - int offset = 0; - char *read_string; - - dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - - if (!dev) { - SLSI_ERR(sdev, "Dev not found\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - - if (!count) - return -EINVAL; - - read_string = kmalloc(count + 1, GFP_KERNEL); - memset(read_string, 0, (count + 1)); - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - offset = slsi_str_to_int(read_string, &qos_info); - if (!offset) { - SLSI_ERR(sdev, "qos info : failed to read a numeric value"); - kfree(read_string); - return -EINVAL; - } - - /*Store the qos info and use it to set MIB during connection*/ - sdev->device_config.qos_info = qos_info; - SLSI_DBG1(sdev, SLSI_MLME, "set qos_info:%d\n", sdev->device_config.qos_info); - - - kfree(read_string); - return count; -} - -static ssize_t slsi_procfs_ap_cert_disable_ht_vht_write(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = file->private_data; - int offset = 0; - int width = 0; - char *read_string; - - if (!count) - return -EINVAL; - - read_string = kmalloc(count + 1, GFP_KERNEL); - memset(read_string, 0, (count + 1)); - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - offset = slsi_str_to_int(read_string, &width); - if (!offset) { - SLSI_ERR(sdev, "Failed to read a numeric value"); - kfree(read_string); - return -EINVAL; - } - - /* Disable default upgrade of corresponding width during AP start */ - if (width == 80) - sdev->allow_switch_80_mhz = false; - else if (width == 40) - sdev->allow_switch_40_mhz = false; - - kfree(read_string); - return count; -} - -static ssize_t slsi_procfs_p2p_certif_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = file->private_data; - char *read_string; - int cert_info = 0; - int offset = 0; - - read_string = kmalloc(count + 1, GFP_KERNEL); - memset(read_string, 0, (count + 1)); - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - offset = slsi_str_to_int(read_string, &cert_info); - if (!offset) { - SLSI_ERR(sdev, "qos info : failed to read a numeric value"); - kfree(read_string); - return -EINVAL; - } - sdev->p2p_certif = cert_info; - kfree(read_string); - return count; -} - -static ssize_t slsi_procfs_p2p_certif_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = file->private_data; - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - SLSI_UNUSED_PARAMETER(file); - - pos += scnprintf(buf + pos, bufsz - pos, "%d\n", sdev->p2p_certif); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static int slsi_procfs_mac_addr_show(struct seq_file *m, void *v) -{ - struct slsi_dev *sdev = (struct slsi_dev *)m->private; - - SLSI_UNUSED_PARAMETER(v); - - seq_printf(m, "%pM", sdev->hw_addr); - return 0; -} - -static ssize_t slsi_procfs_create_tspec_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = file->private_data; - static const char *extra_info = ""; - - return slsi_procfs_read_int(file, user_buf, count, ppos, sdev->current_tspec_id, extra_info); -} - -static ssize_t slsi_procfs_create_tspec_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sfdev = (struct slsi_dev *)file->private_data; - char *read_string = kmalloc(count + 1, GFP_KERNEL); - - if (!read_string) { - SLSI_ERR(sfdev, "Malloc for read_string failed\n"); - return -ENOMEM; - } - - if (!count) { - kfree(read_string); - return 0; - } - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - sfdev->current_tspec_id = cac_ctrl_create_tspec(sfdev, read_string); - if (sfdev->current_tspec_id < 0) { - SLSI_ERR(sfdev, "create tspec: No parameters or not valid parameters\n"); - kfree(read_string); - return -EINVAL; - } - kfree(read_string); - - return count; -} - -static ssize_t slsi_procfs_confg_tspec_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - static const char *extra_info = "Not implemented yet"; - int value = 10; - - return slsi_procfs_read_int(file, user_buf, count, ppos, value, extra_info); -} - -static ssize_t slsi_procfs_confg_tspec_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sfdev = (struct slsi_dev *)file->private_data; - char *read_string = kmalloc(count + 1, GFP_KERNEL); - - if (!read_string) { - SLSI_ERR(sfdev, "Malloc for read_string failed\n"); - return -ENOMEM; - } - - if (!count) { - kfree(read_string); - return 0; - } - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - /* to do: call to config_tspec() to configure a tspec field */ - if (cac_ctrl_config_tspec(sfdev, read_string) < 0) { - SLSI_ERR(sfdev, "config tspec error\n"); - kfree(read_string); - return -EINVAL; - } - - kfree(read_string); - - return count; -} - -static ssize_t slsi_procfs_send_addts_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = file->private_data; - static const char *extra_info = ""; - - return slsi_procfs_read_int(file, user_buf, count, ppos, sdev->tspec_error_code, extra_info); -} - -static ssize_t slsi_procfs_send_addts_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sfdev = (struct slsi_dev *)file->private_data; - char *read_string = kmalloc(count + 1, GFP_KERNEL); - - if (!read_string) { - SLSI_ERR(sfdev, "Malloc for read_string failed\n"); - return -ENOMEM; - } - - sfdev->tspec_error_code = -1; - if (!count) { - kfree(read_string); - return 0; - } - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - /* to do: call to config_tspec() to configure a tspec field */ - if (cac_ctrl_send_addts(sfdev, read_string) < 0) { - SLSI_ERR(sfdev, "send addts error\n"); - kfree(read_string); - return -EINVAL; - } - kfree(read_string); - return count; -} - -static ssize_t slsi_procfs_send_delts_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = file->private_data; - static const char *extra_info = ""; - - return slsi_procfs_read_int(file, user_buf, count, ppos, sdev->tspec_error_code, extra_info); -} - -static ssize_t slsi_procfs_send_delts_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sfdev = (struct slsi_dev *)file->private_data; - char *read_string = kmalloc(count + 1, GFP_KERNEL); - - if (!read_string) { - SLSI_ERR(sfdev, "Malloc for read_string failed\n"); - return -ENOMEM; - } - - sfdev->tspec_error_code = -1; - - if (!count) { - kfree(read_string); - return 0; - } - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - /* to do: call to config_tspec() to configure a tspec field */ - if (cac_ctrl_send_delts(sfdev, read_string) < 0) { - SLSI_ERR(sfdev, "send delts error\n"); - kfree(read_string); - return -EINVAL; - } - kfree(read_string); - return count; -} - -static ssize_t slsi_procfs_del_tspec_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - static const char *extra_info = "Not implemented yet"; - int value = 10; - - return slsi_procfs_read_int(file, user_buf, count, ppos, value, extra_info); -} - -static ssize_t slsi_procfs_del_tspec_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sfdev = (struct slsi_dev *)file->private_data; - char *read_string = kmalloc(count + 1, GFP_KERNEL); - - if (!read_string) { - SLSI_ERR(sfdev, "Malloc for read_string failed\n"); - return -ENOMEM; - } - - if (!count) { - kfree(read_string); - return 0; - } - - simple_write_to_buffer(read_string, count, ppos, user_buf, count); - read_string[count] = '\0'; - - /* to do: call to config_tspec() to configure a tspec field */ - if (cac_ctrl_delete_tspec(sfdev, read_string) < 0) { - SLSI_ERR(sfdev, "config tspec error\n"); - kfree(read_string); - return -EINVAL; - } - kfree(read_string); - return count; -} - -static ssize_t slsi_procfs_tput_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - struct net_device *dev; - struct netdev_vif *ndev_vif; - int i; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) { - dev = sdev->netdev[i]; - if (dev) { - ndev_vif = netdev_priv(dev); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t", dev->name); - if (ndev_vif->throughput_tx_bps < 1000) - pos += scnprintf(buf + pos, bufsz - pos, "TX:%u bps\t", ndev_vif->throughput_tx_bps); - else if ((ndev_vif->throughput_tx_bps >= 1000) && (ndev_vif->throughput_tx_bps < (1000 * 1000))) - pos += scnprintf(buf + pos, bufsz - pos, "TX:%u Kbps\t", (ndev_vif->throughput_tx_bps / 1000)); - else - pos += scnprintf(buf + pos, bufsz - pos, "TX:%u Mbps\t", (ndev_vif->throughput_tx_bps / (1000 * 1000))); - - if (ndev_vif->throughput_rx_bps < 1000) - pos += scnprintf(buf + pos, bufsz - pos, "RX:%u bps\n", ndev_vif->throughput_rx_bps); - else if ((ndev_vif->throughput_rx_bps >= 1000) && (ndev_vif->throughput_rx_bps < (1000 * 1000))) - pos += scnprintf(buf + pos, bufsz - pos, "RX:%u Kbps\n", (ndev_vif->throughput_rx_bps / 1000)); - else - pos += scnprintf(buf + pos, bufsz - pos, "RX:%u Mbps\n", (ndev_vif->throughput_rx_bps / (1000 * 1000))); - } - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t slsi_procfs_tput_write(struct file *file, const char __user *user_buf, size_t len, loff_t *ppos) -{ - struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - char read_buf[2]; - - if (!sdev) { - SLSI_ERR(sdev, "invalid sdev\n"); - return -ENOMEM; - } - - if (!len || (len > sizeof(read_buf))) { - SLSI_ERR(sdev, "invalid len\n"); - return -EINVAL; - } - - simple_write_to_buffer(read_buf, len, ppos, user_buf, len); - - switch (read_buf[0]) { - case '1': - if (!slsi_traffic_mon_is_running(sdev)) { - SLSI_DBG1(sdev, SLSI_HIP, "start Traffic monitor\n"); - slsi_traffic_mon_client_register(sdev, sdev, 0, 0, 0, NULL); - } - break; - case '0': - SLSI_DBG1(sdev, SLSI_HIP, "stop Traffic monitor\n"); - slsi_traffic_mon_client_unregister(sdev, sdev); - break; - default: - SLSI_DBG1(sdev, SLSI_HIP, "invalid value %c\n", read_buf[0]); - return -EINVAL; - } - return len; -} - -static atomic_t fd_opened_count; - -void slsi_procfs_inc_node(void) -{ - atomic_inc(&fd_opened_count); -} - -void slsi_procfs_dec_node(void) -{ - if (0 == atomic_read(&fd_opened_count)) { - WARN_ON(1); - return; - } - atomic_dec(&fd_opened_count); -} - -static ssize_t slsi_procfs_fd_opened_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - SLSI_UNUSED_PARAMETER(file); - - pos += scnprintf(buf + pos, bufsz - pos, "%d\n", atomic_read(&fd_opened_count)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static int slsi_procfs_fcq_show(struct seq_file *m, void *v) -{ - struct slsi_dev *sdev = (struct slsi_dev *)m->private; - int ac; - s32 vif, i; - - SLSI_UNUSED_PARAMETER(v); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (vif = 1; vif <= CONFIG_SCSC_WLAN_MAX_INTERFACES; vif++) { - struct net_device *dev = slsi_get_netdev_locked(sdev, vif); - struct netdev_vif *ndev_vif; - - if (!dev) - continue; - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - /* Unicast */ - for (i = 0; i < SLSI_ADHOC_PEER_CONNECTIONS_MAX; i++) { - struct slsi_peer *peer = ndev_vif->peer_sta_record[i]; - int smod = 0, scod = 0, qmod = 0, qcod = 0; - struct scsc_wifi_fcq_q_stat queue_stat; - u32 peer_ps_state_transitions = 0; - enum scsc_wifi_fcq_8021x_state cp_state; - - if (!peer || !peer->valid) - continue; - - if (scsc_wifi_fcq_stat_queueset(&peer->data_qs, &queue_stat, &smod, &scod, &cp_state, &peer_ps_state_transitions) != 0) - continue; - - seq_printf(m, "|%-12s|%-6d|%-6s|\n%d). peer:%pM, qs:%2d, smod:%u, scod:%u, netq stops :%u, netq resumes :%u, PS transitions :%u Controlled port :%s\n", - netdev_name(dev), - vif, - "UCAST", - i + 1, - peer->address, - peer->queueset, - smod, - scod, - queue_stat.netq_stops, - queue_stat.netq_resumes, - peer_ps_state_transitions, - cp_state == SCSC_WIFI_FCQ_8021x_STATE_BLOCKED ? "Blocked" : "Opened"); - - seq_printf(m, " |%-12s|%-17s|%4s|%8s|%8s|%8s|%8s|%10s|%8s|\n", - "netdev", - "peer", - "AC index", "qcod", "qmod", - "nq_state", "nq_stop", "nq_resume", - "tq_state"); - - for (ac = 0; ac < SLSI_NETIF_Q_PER_PEER; ac++) { - if (scsc_wifi_fcq_stat_queue(&peer->data_qs.ac_q[ac].head, - &queue_stat, - &qmod, &qcod) == 0) - seq_printf(m, " |%-12s|%pM|%4d|%8u|%8u|%8u|%8u\n", - netdev_name(dev), - peer->address, - ac, - qcod, - qmod, - queue_stat.netq_stops, - queue_stat.netq_resumes); - else - break; - } - } - - /* Groupcast */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) { - int smod = 0, scod = 0, qmod = 0, qcod = 0; - struct scsc_wifi_fcq_q_stat queue_stat; - u32 peer_ps_state_transitions = 0; - enum scsc_wifi_fcq_8021x_state cp_state; - - if (scsc_wifi_fcq_stat_queueset(&ndev_vif->ap.group_data_qs, &queue_stat, &smod, &scod, &cp_state, &peer_ps_state_transitions) != 0) - continue; - - seq_printf(m, "|%-12s|%-6d|%-6s|\n%d). smod:%u, scod:%u, netq stops :%u, netq resumes :%u, PS transitions :%u Controlled port :%s\n", - netdev_name(dev), - vif, - "MCAST", - i + 1, - smod, - scod, - queue_stat.netq_stops, - queue_stat.netq_resumes, - peer_ps_state_transitions, - cp_state == SCSC_WIFI_FCQ_8021x_STATE_BLOCKED ? "Blocked" : "Opened"); - - seq_printf(m, " |%-12s|%4s|%8s|%8s|%8s|%8s|%10s|%8s|\n", - "netdev", - "AC index", "qcod", "qmod", - "nq_state", "nq_stop", "nq_resume", - "tq_state"); - - for (ac = 0; ac < SLSI_NETIF_Q_PER_PEER; ac++) { - if (scsc_wifi_fcq_stat_queue(&ndev_vif->ap.group_data_qs.ac_q[ac].head, - &queue_stat, - &qmod, &qcod) == 0) - seq_printf(m, " |%-12s|%4d|%8u|%8u|%8u|%8u\n", - netdev_name(dev), - ac, - qcod, - qmod, - queue_stat.netq_stops, - queue_stat.netq_resumes); - else - break; - } - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } - - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - return 0; -} - -static int slsi_procfs_tcp_ack_suppression_show(struct seq_file *m, void *v) -{ - struct slsi_dev *sdev = (struct slsi_dev *)m->private; - struct net_device *dev; - struct netdev_vif *ndev_vif; - int i; - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) { - dev = sdev->netdev[i]; - if (dev) { - ndev_vif = netdev_priv(dev); - - seq_printf(m, "%s: tack_acks=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_acks); - seq_printf(m, "%s: tack_suppressed=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_suppressed); - seq_printf(m, "%s: tack_sent=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_sent); - seq_printf(m, "%s: tack_max=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_max); - seq_printf(m, "%s: tack_timeout=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_timeout); - seq_printf(m, "%s: tack_aged=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_ktime); - seq_printf(m, "%s: tack_dacks=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_dacks); - seq_printf(m, "%s: tack_sacks=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_sacks); - seq_printf(m, "%s: tack_delay_acks=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_delay_acks); - seq_printf(m, "%s: tack_low_window=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_low_window); - seq_printf(m, "%s: tack_ece=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_ece); - seq_printf(m, "%s: tack_nocache=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_nocache); - seq_printf(m, "%s: tack_norecord=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_norecord); - seq_printf(m, "%s: tack_lastrecord=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_lastrecord); - seq_printf(m, "%s: tack_searchrecord=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_searchrecord); - seq_printf(m, "%s: tack_hasdata=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_hasdata); - seq_printf(m, "%s: tack_psh=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_psh); - seq_printf(m, "%s: tack_dropped=%u\n", dev->name, ndev_vif->tcp_ack_stats.tack_dropped); - - /* reset stats after it is read */ - memset(&ndev_vif->tcp_ack_stats, 0, sizeof(struct slsi_tcp_ack_stats)); - } - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - return 0; -} - -static ssize_t slsi_procfs_nan_mac_addr_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -{ - char buf[20]; - char nan_mac[ETH_ALEN]; - int pos = 0; -#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE - struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - - slsi_nan_get_mac(sdev, nan_mac); -#else - - SLSI_UNUSED_PARAMETER(file); - memset(nan_mac, 0, ETH_ALEN); -#endif - pos = scnprintf(buf, sizeof(buf), "%pM", nan_mac); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -SLSI_PROCFS_SEQ_FILE_OPS(vifs); -SLSI_PROCFS_SEQ_FILE_OPS(mac_addr); -SLSI_PROCFS_WRITE_FILE_OPS(uapsd); -SLSI_PROCFS_WRITE_FILE_OPS(ap_cert_disable_ht_vht); -SLSI_PROCFS_RW_FILE_OPS(p2p_certif); -SLSI_PROCFS_RW_FILE_OPS(create_tspec); -SLSI_PROCFS_RW_FILE_OPS(confg_tspec); -SLSI_PROCFS_RW_FILE_OPS(send_addts); -SLSI_PROCFS_RW_FILE_OPS(send_delts); -SLSI_PROCFS_RW_FILE_OPS(del_tspec); -SLSI_PROCFS_RW_FILE_OPS(tput); -SLSI_PROCFS_READ_FILE_OPS(fd_opened); -SLSI_PROCFS_SEQ_FILE_OPS(build); -SLSI_PROCFS_SEQ_FILE_OPS(status); -SLSI_PROCFS_SEQ_FILE_OPS(fcq); -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG -SLSI_PROCFS_READ_FILE_OPS(mutex_stats); -#endif -SLSI_PROCFS_READ_FILE_OPS(sta_bss); -SLSI_PROCFS_READ_FILE_OPS(big_data); -SLSI_PROCFS_READ_FILE_OPS(throughput_stats); -SLSI_PROCFS_SEQ_FILE_OPS(tcp_ack_suppression); -SLSI_PROCFS_READ_FILE_OPS(nan_mac_addr); - - -int slsi_create_proc_dir(struct slsi_dev *sdev) -{ - char dir[16]; - struct proc_dir_entry *parent; - - (void)snprintf(dir, sizeof(dir), "driver/unifi%d", sdev->procfs_instance); - parent = proc_mkdir(dir, NULL); - if (parent) { -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0)) - parent->data = sdev; -#endif - sdev->procfs_dir = parent; - - SLSI_PROCFS_SEQ_ADD_FILE(sdev, build, parent, S_IRUSR | S_IRGRP | S_IROTH); - SLSI_PROCFS_SEQ_ADD_FILE(sdev, status, parent, S_IRUSR | S_IRGRP | S_IROTH); - SLSI_PROCFS_SEQ_ADD_FILE(sdev, fcq, parent, S_IRUSR | S_IRGRP | S_IROTH); - SLSI_PROCFS_SEQ_ADD_FILE(sdev, vifs, parent, S_IRUSR | S_IRGRP); - SLSI_PROCFS_SEQ_ADD_FILE(sdev, mac_addr, parent, S_IRUSR | S_IRGRP | S_IROTH); /*Add S_IROTH permission so that android settings can access it*/ - SLSI_PROCFS_ADD_FILE(sdev, uapsd, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, ap_cert_disable_ht_vht, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, p2p_certif, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, create_tspec, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, confg_tspec, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, send_addts, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, send_delts, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, del_tspec, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, tput, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, fd_opened, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - SLSI_PROCFS_ADD_FILE(sdev, mutex_stats, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -#endif - SLSI_PROCFS_ADD_FILE(sdev, sta_bss, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, big_data, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_ADD_FILE(sdev, throughput_stats, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - SLSI_PROCFS_SEQ_ADD_FILE(sdev, tcp_ack_suppression, sdev->procfs_dir, S_IRUSR | S_IRGRP); - SLSI_PROCFS_ADD_FILE(sdev, nan_mac_addr, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - return 0; - } - -err: - SLSI_DBG1(sdev, SLSI_HIP, "Failure in creation of proc directories\n"); - return -EINVAL; -} - -void slsi_remove_proc_dir(struct slsi_dev *sdev) -{ - if (sdev->procfs_dir) { - char dir[32]; - - SLSI_PROCFS_REMOVE_FILE(build, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(release, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(version, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(status, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(vifs, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(mac_addr, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(fcq, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(uapsd, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(ap_cert_disable_ht_vht, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(p2p_certif, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(create_tspec, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(confg_tspec, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(send_addts, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(send_delts, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(del_tspec, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(tput, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(fd_opened, sdev->procfs_dir); -#ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG - SLSI_PROCFS_REMOVE_FILE(mutex_stats, sdev->procfs_dir); -#endif - SLSI_PROCFS_REMOVE_FILE(sta_bss, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(big_data, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(throughput_stats, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(tcp_ack_suppression, sdev->procfs_dir); - SLSI_PROCFS_REMOVE_FILE(nan_mac_addr, sdev->procfs_dir); - - (void)snprintf(dir, sizeof(dir), "driver/unifi%d", sdev->procfs_instance); - remove_proc_entry(dir, NULL); - sdev->procfs_dir = NULL; - } -} diff --git a/drivers/net/wireless/scsc/procfs.h b/drivers/net/wireless/scsc/procfs.h deleted file mode 100644 index 9a67bd6719ec..000000000000 --- a/drivers/net/wireless/scsc/procfs.h +++ /dev/null @@ -1,127 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef __SLSI_PROCFS_H__ -#define __SLSI_PROCFS_H__ - -#include -#include -#include -#include - -struct slsi_dev; -struct slsi_vif; - -#ifdef CONFIG_SCSC_WLAN_ANDROID -# ifndef AID_WIFI -# define AID_WIFI 1010 -# endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define SLSI_PROCFS_SET_UID_GID(_entry) \ - do { \ - kuid_t proc_kuid = KUIDT_INIT(AID_WIFI); \ - kgid_t proc_kgid = KGIDT_INIT(AID_WIFI); \ - proc_set_user(_entry, proc_kuid, proc_kgid); \ - } while (0) -#else -#define SLSI_PROCFS_SET_UID_GID(entry) \ - do { \ - (entry)->uid = AID_WIFI; \ - (entry)->gid = AID_WIFI; \ - } while (0) -#endif -#else -#define SLSI_PROCFS_SET_UID_GID(entry) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define SLSI_PDE_DATA(inode) PDE_DATA(inode) -#else -#define SLSI_PDE_DATA(inode) (PDE(inode)->data) -#endif - -/* procfs operations */ -int slsi_create_proc_dir(struct slsi_dev *sdev); -void slsi_remove_proc_dir(struct slsi_dev *sdev); - -int slsi_procfs_open_file_generic(struct inode *inode, struct file *file); - -#define SLSI_PROCFS_SEQ_FILE_OPS(name) \ - static int slsi_procfs_ ## name ## _show(struct seq_file *m, void *v); \ - static int slsi_procfs_ ## name ## _open(struct inode *inode, struct file *file) \ - { \ - return single_open(file, slsi_procfs_ ## name ## _show, SLSI_PDE_DATA(inode)); \ - } \ - static const struct file_operations slsi_procfs_ ## name ## _fops = { \ - .open = slsi_procfs_ ## name ## _open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - } - -#define SLSI_PROCFS_SEQ_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = proc_create_data(# name, mode, parent, &slsi_procfs_ ## name ## _fops, _sdev); \ - if (!entry) { \ - goto err; \ - } \ - SLSI_PROCFS_SET_UID_GID(entry); \ - } while (0) - -#define SLSI_PROCFS_READ_FILE_OPS(name) \ - static ssize_t slsi_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations slsi_procfs_ ## name ## _fops = { \ - .read = slsi_procfs_ ## name ## _read, \ - .open = slsi_procfs_open_file_generic, \ - .llseek = generic_file_llseek \ - } - -#define SLSI_PROCFS_WRITE_FILE_OPS(name) \ - static ssize_t slsi_procfs_ ## name ## _write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations slsi_procfs_ ## name ## _fops = { \ - .write = slsi_procfs_ ## name ## _write, \ - .open = slsi_procfs_open_file_generic, \ - .llseek = generic_file_llseek \ - } - -#define SLSI_PROCFS_RW_FILE_OPS(name) \ - static ssize_t slsi_procfs_ ## name ## _write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); \ - static ssize_t slsi_procfs_ ## name ## _read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); \ - static const struct file_operations slsi_procfs_ ## name ## _fops = { \ - .read = slsi_procfs_ ## name ## _read, \ - .write = slsi_procfs_ ## name ## _write, \ - .open = slsi_procfs_open_file_generic, \ - .llseek = generic_file_llseek \ - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) -#define SLSI_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry = proc_create_data(# name, mode, parent, &slsi_procfs_ ## name ## _fops, _sdev); \ - SLSI_PROCFS_SET_UID_GID(entry); \ - } while (0) -#else -#define SLSI_PROCFS_ADD_FILE(_sdev, name, parent, mode) \ - do { \ - struct proc_dir_entry *entry; \ - entry = create_proc_entry(# name, mode, parent); \ - if (entry) { \ - entry->proc_fops = &slsi_procfs_ ## name ## _fops; \ - entry->data = _sdev; \ - SLSI_PROCFS_SET_UID_GID(entry); \ - } else { \ - goto err; \ - } \ - } while (0) -#endif -#define SLSI_PROCFS_REMOVE_FILE(name, parent) remove_proc_entry(# name, parent) - -void slsi_procfs_inc_node(void); -void slsi_procfs_dec_node(void); - -#endif diff --git a/drivers/net/wireless/scsc/rx.c b/drivers/net/wireless/scsc/rx.c deleted file mode 100755 index 2138663db1d9..000000000000 --- a/drivers/net/wireless/scsc/rx.c +++ /dev/null @@ -1,2838 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include - -#include "debug.h" -#include "dev.h" -#include "mgt.h" -#include "mlme.h" -#include "src_sink.h" -#include "const.h" -#include "ba.h" -#include "mib.h" -#include "cac.h" -#include "nl80211_vendor.h" - -#ifdef CONFIG_ANDROID -#include "scsc_wifilogger_rings.h" -#endif - -#ifdef CONFIG_SCSC_LOG_COLLECTION -#include -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) -#include "porting_imx.h" -#endif -struct ieee80211_channel *slsi_find_scan_channel(struct slsi_dev *sdev, struct ieee80211_mgmt *mgmt, size_t mgmt_len, u16 freq) -{ - int ielen = mgmt_len - (mgmt->u.beacon.variable - (u8 *)mgmt); - const u8 *scan_ds = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, ielen); - const u8 *scan_ht = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable, ielen); - u8 chan = 0; - - /* Use the DS or HT channel where possible as the Offchannel results mean the RX freq is not reliable */ - if (scan_ds) - chan = scan_ds[2]; - else if (scan_ht) - chan = scan_ht[2]; - - if (chan) { - enum nl80211_band band = NL80211_BAND_2GHZ; - - if (chan > 14) - band = NL80211_BAND_5GHZ; - freq = (u16)ieee80211_channel_to_frequency(chan, band); - } - if (!freq) - return NULL; - - return ieee80211_get_channel(sdev->wiphy, freq); -} - -static struct ieee80211_mgmt *slsi_rx_scan_update_ssid(struct slsi_dev *sdev, struct net_device *dev, - struct ieee80211_mgmt *mgmt, size_t mgmt_len, size_t *new_len, - u16 freq) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u8 *new_mgmt; - int offset; - const u8 *mgmt_pos; - const u8 *ssid; - int i; - int band; - - if (!SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) - return NULL; - - /* update beacon, not probe response as probe response will always have actual ssid.*/ - if (!ieee80211_is_beacon(mgmt->frame_control)) - return NULL; - - ssid = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, - mgmt_len - (mgmt->u.beacon.variable - (u8 *)mgmt)); - if (!ssid) { - SLSI_WARN(sdev, "beacon with NO SSID IE\n"); - return NULL; - } - /* update beacon only if hidden ssid. So, Skip if not hidden ssid*/ - if ((ssid[1] > 0) && (ssid[2] != '\0')) - return NULL; - - band = (freq / 1000) == 2 ? SLSI_FREQ_BAND_2GHZ : SLSI_FREQ_BAND_5GHZ; - - /* check we have a known ssid for a bss */ - for (i = 0; i < SLSI_SCAN_SSID_MAP_MAX; i++) { - if (SLSI_ETHER_EQUAL(sdev->ssid_map[i].bssid, mgmt->bssid) && (sdev->ssid_map[i].band == band)) { - new_mgmt = kmalloc(mgmt_len + 34, GFP_KERNEL); - if (!new_mgmt) { - SLSI_ERR_NODEV("malloc failed(len:%ld)\n", mgmt_len + 34); - return NULL; - } - - /* copy frame till ssid element */ - memcpy(new_mgmt, mgmt, ssid - (u8 *)mgmt); - offset = ssid - (u8 *)mgmt; - /* copy bss ssid into new frame */ - new_mgmt[offset++] = WLAN_EID_SSID; - new_mgmt[offset++] = sdev->ssid_map[i].ssid_len; - memcpy(new_mgmt + offset, sdev->ssid_map[i].ssid, sdev->ssid_map[i].ssid_len); - offset += sdev->ssid_map[i].ssid_len; - /* copy rest of the frame following ssid */ - mgmt_pos = ssid + ssid[1] + 2; - memcpy(new_mgmt + offset, mgmt_pos, mgmt_len - (mgmt_pos - (u8 *)mgmt)); - offset += mgmt_len - (mgmt_pos - (u8 *)mgmt); - *new_len = offset; - - return (struct ieee80211_mgmt *)new_mgmt; - } - } - return NULL; -} - -void slsi_rx_scan_pass_to_cfg80211(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - size_t mgmt_len = fapi_get_mgmtlen(skb); - s32 signal = fapi_get_s16(skb, u.mlme_scan_ind.rssi) * 100; - u16 freq = SLSI_FREQ_FW_TO_HOST(fapi_get_u16(skb, u.mlme_scan_ind.channel_frequency)); - struct ieee80211_channel *channel = slsi_find_scan_channel(sdev, mgmt, mgmt_len, freq); - struct timespec uptime; - - get_monotonic_boottime(&uptime); - SLSI_UNUSED_PARAMETER(dev); - - /* update timestamp with device uptime in micro sec */ - mgmt->u.beacon.timestamp = (uptime.tv_sec * 1000000) + (uptime.tv_nsec / 1000); - - if (channel) { - struct cfg80211_bss *bss; - struct ieee80211_mgmt *mgmt_new; - size_t mgmt_new_len = 0; - - mgmt_new = slsi_rx_scan_update_ssid(sdev, dev, mgmt, mgmt_len, &mgmt_new_len, freq); - if (mgmt_new) - bss = cfg80211_inform_bss_frame(sdev->wiphy, channel, mgmt_new, mgmt_new_len, signal, GFP_KERNEL); - else - bss = cfg80211_inform_bss_frame(sdev->wiphy, channel, mgmt, mgmt_len, signal, GFP_KERNEL); - - slsi_cfg80211_put_bss(sdev->wiphy, bss); - kfree(mgmt_new); - } else { - SLSI_NET_DBG1(dev, SLSI_MLME, "No Channel info found for freq:%d\n", freq); - } - - slsi_kfree_skb(skb); -} - -static int slsi_add_to_scan_list(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, - struct sk_buff *skb, const u8 *scan_ssid, u16 scan_id) -{ - struct slsi_scan_result *head; - struct slsi_scan_result *scan_result, *current_result, *prev = NULL; - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - bool found = 0, skb_stored = 0; - int current_rssi, current_band; - - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - head = ndev_vif->scan[scan_id].scan_results; - scan_result = head; - current_rssi = fapi_get_s16(skb, u.mlme_scan_ind.rssi); - current_band = (fapi_get_s16(skb, - u.mlme_scan_ind.channel_frequency) / - 2000) == 2 ? SLSI_FREQ_BAND_2GHZ : SLSI_FREQ_BAND_5GHZ; - - while (scan_result) { - if (SLSI_ETHER_EQUAL(scan_result->bssid, mgmt->bssid) && (scan_result->band == current_band)) { - /*entry exists for bssid*/ - if (!scan_result->probe_resp && ieee80211_is_probe_resp(mgmt->frame_control)) { - scan_result->probe_resp = skb; - skb_stored = 1; - } else if (!scan_result->beacon && ieee80211_is_beacon(mgmt->frame_control)) { - scan_result->beacon = skb; - skb_stored = 1; - if (!scan_ssid || !scan_ssid[1] || scan_ssid[2] == '\0') - scan_result->hidden = 1; - } - - /* Use the best RSSI value from all beacons/probe resp for a bssid. If no improvment - * in RSSI and beacon and probe response exist, ignore this result - */ - if (current_rssi < scan_result->rssi) { - if (!skb_stored) - slsi_kfree_skb(skb); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - return 0; - } - - scan_result->rssi = current_rssi; - if (!skb_stored) { - if (ieee80211_is_beacon(mgmt->frame_control)) { - slsi_kfree_skb(scan_result->beacon); - scan_result->beacon = skb; - } else { - slsi_kfree_skb(scan_result->probe_resp); - scan_result->probe_resp = skb; - } - } - - /*No change in position if rssi is still less than prev node*/ - if (!prev || (prev->rssi > current_rssi)) { - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - return 0; - } - - /*remove and re-insert*/ - found = 1; - prev->next = scan_result->next; - scan_result->next = NULL; - current_result = scan_result; - - break; - } - - prev = scan_result; - scan_result = scan_result->next; - } - - if (!found) { - /*add_new node*/ - current_result = kzalloc(sizeof(*current_result), GFP_KERNEL); - if (!current_result) { - SLSI_ERR(sdev, "Failed to allocate node for scan result\n"); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - return -1; - } - SLSI_ETHER_COPY(current_result->bssid, mgmt->bssid); - - current_result->rssi = current_rssi; - current_result->band = current_band; - if (ieee80211_is_beacon(mgmt->frame_control)) { - current_result->beacon = skb; - if (!scan_ssid || !scan_ssid[1] || scan_ssid[2] == '\0') - current_result->hidden = 1; - } else { - current_result->probe_resp = skb; - } - current_result->next = NULL; - - if (!head) { /*first node*/ - ndev_vif->scan[scan_id].scan_results = current_result; - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - return 0; - } - } - - scan_result = head; - prev = NULL; - /* insert based on rssi in descending order*/ - while (scan_result) { - if (current_result->rssi > scan_result->rssi) { - current_result->next = scan_result; - if (prev) - prev->next = current_result; - else - ndev_vif->scan[scan_id].scan_results = current_result; - break; - } - prev = scan_result; - scan_result = scan_result->next; - } - if (!scan_result) { - /*insert at the end*/ - prev->next = current_result; - current_result->next = NULL; - } - - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - return 0; -} - -static int slsi_add_to_p2p_scan_list(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, - struct sk_buff *skb, u16 scan_id) -{ - struct slsi_scan_result *current_result; - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - struct slsi_scan *scan; - - /*add_new node*/ - current_result = kzalloc(sizeof(*current_result), GFP_KERNEL); - if (!current_result) { - SLSI_ERR(sdev, "Failed to allocate node for scan result\n"); - return -1; - } - SLSI_ETHER_COPY(current_result->bssid, mgmt->bssid); - - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - scan = &ndev_vif->scan[scan_id]; - if (ieee80211_is_beacon(mgmt->frame_control)) - current_result->beacon = skb; - else - current_result->probe_resp = skb; - - if (!scan->scan_results) { - scan->scan_results = current_result; - current_result->next = NULL; - } else { - current_result->next = scan->scan_results; - scan->scan_results = current_result; - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - - return 0; -} - -void slsi_rx_scan_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 scan_id = fapi_get_u16(skb, u.mlme_scan_ind.scan_id); - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - size_t mgmt_len = fapi_get_mgmtlen(skb); - size_t ie_len = mgmt_len - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - const u8 *scan_ssid = NULL; - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - if (slsi_is_gscan_id(scan_id)) { - SLSI_NET_DBG3(dev, SLSI_GSCAN, "scan_id:%#x bssid:%pM\n", scan_id, fapi_get_mgmt(skb)->bssid); - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - slsi_gscan_handle_scan_result(sdev, dev, skb, scan_id, false); - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - return; - } -#endif - - scan_ssid = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_resp.variable, ie_len); - - if (sdev->p2p_certif && (ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) && (scan_id == (ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID))) { - /* When supplicant receives a peer GO probe response with selected registrar set and group capability as 0, - * which is invalid, it is unable to store persistent network block. Hence such probe response is getting ignored here. - * This is mainly for an inter-op with Realtek P2P GO in P2P certification - */ - if (scan_ssid && scan_ssid[1] > 7) { - const u8 *p2p_ie = NULL; - - p2p_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, mgmt->u.probe_resp.variable, ie_len); -#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1) - if (p2p_ie && !(p2p_ie[10] & P2P_GROUP_CAPAB_PERSISTENT_GROUP)) { - SLSI_NET_INFO(dev, "Ignoring a peer GO probe response with group_capab as 0\n"); - slsi_kfree_skb(skb); - return; - } - } - } - - scan_id = (scan_id & 0xFF); - - if (WARN_ON(scan_id >= SLSI_SCAN_MAX)) { - slsi_kfree_skb(skb); - return; - } - - /* Blocking scans already taken scan mutex. - * So scan mutex only incase of non blocking scans. - */ - if (!ndev_vif->scan[scan_id].is_blocking_scan) - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - - if (fapi_get_vif(skb) != 0 && fapi_get_u16(skb, u.mlme_scan_ind.scan_id) == 0) { - /* Connect/Roaming scan data : Save for processing later */ - SLSI_NET_DBG1(dev, SLSI_MLME, "Connect/Roaming scan indication received, bssid:%pM\n", fapi_get_mgmt(skb)->bssid); - slsi_kfree_skb(ndev_vif->sta.mlme_scan_ind_skb); - ndev_vif->sta.mlme_scan_ind_skb = skb; - } else if (ndev_vif->scan[scan_id].scan_req || ndev_vif->scan[scan_id].sched_req || - ndev_vif->scan[scan_id].acs_request || - ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan) { - slsi_roam_channel_cache_add(sdev, dev, skb); - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) - slsi_add_to_scan_list(sdev, ndev_vif, skb, scan_ssid, scan_id); - else - slsi_add_to_p2p_scan_list(sdev, ndev_vif, skb, scan_id); - } - - if (!ndev_vif->scan[scan_id].is_blocking_scan) - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); -} - -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -void slsi_rx_beacon_reporting_event_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 reason_code = fapi_get_u16(skb, u.mlme_beacon_reporting_event_ind.abort_reason) - - SLSI_FORWARD_BEACON_ABORT_REASON_OFFSET; - int ret = 0; - - if (!ndev_vif->is_wips_running) { - SLSI_ERR(sdev, "WIPS is not running. Ignore beacon_reporting_event_ind(%u)\n", reason_code); - return; - } - - ndev_vif->is_wips_running = false; - - if (reason_code >= SLSI_FORWARD_BEACON_ABORT_REASON_UNSPECIFIED && - reason_code <= SLSI_FORWARD_BEACON_ABORT_REASON_SUSPENDED) { - SLSI_INFO(sdev, "received abort_event from FW with reason(%u)\n", reason_code); - } else { - SLSI_ERR(sdev, "received abort_event unsupporting reason(%u)\n", reason_code); - } - - ret = slsi_send_forward_beacon_abort_vendor_event(sdev, reason_code); - if (ret) - SLSI_ERR(sdev, "Failed to send forward_beacon_abort_event(err=%d)\n", ret); -} - -void slsi_handle_wips_beacon(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, - struct ieee80211_mgmt *mgmt, int mgmt_len) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - size_t ie_len = mgmt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - const u8 *ssid_ie = NULL; - const u8 *scan_ssid = NULL; - const u8 *scan_bssid = NULL; - u16 beacon_int = 0; - u64 timestamp = 0; - int ssid_len = 0; - struct timespec sys_time; - int ret = 0; - - u8 channel = (u8)(ndev_vif->chan->hw_value); - - get_monotonic_boottime(&sys_time); - scan_bssid = fapi_get_mgmt(skb)->bssid; - - ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, ie_len); - ssid_len = ssid_ie[1]; - scan_ssid = &ssid_ie[2]; - beacon_int = mgmt->u.beacon.beacon_int; - timestamp = mgmt->u.beacon.timestamp; - - SLSI_NET_DBG2(dev, SLSI_RX, - "forward_beacon from bssid:%pM beacon_int:%u timestamp:%llu system_time:%llu\n", - fapi_get_mgmt(skb)->bssid, beacon_int, timestamp, - (u64)TIMESPEC_TO_US(sys_time)); - - ret = slsi_send_forward_beacon_vendor_event(sdev, scan_ssid, ssid_len, scan_bssid, - channel, beacon_int, timestamp, - (u64)TIMESPEC_TO_US(sys_time)); - if (ret) - SLSI_ERR(sdev, "Failed to forward beacon_event\n"); -} -#endif - -static void slsi_scan_update_ssid_map(struct slsi_dev *sdev, struct net_device *dev, u16 scan_id) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct ieee80211_mgmt *mgmt; - const u8 *ssid_ie = NULL, *connected_ssid = NULL; - int i, found = 0, is_connected = 0; - struct slsi_scan_result *scan_result = NULL; - int band; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_result_mutex)); - - if (ndev_vif->activated && ndev_vif->vif_type == FAPI_VIFTYPE_STATION && ndev_vif->sta.sta_bss) { - band = (ndev_vif->sta.sta_bss->channel->center_freq / - 1000) == 2 ? SLSI_FREQ_BAND_2GHZ : SLSI_FREQ_BAND_5GHZ; - is_connected = 1; - connected_ssid = cfg80211_find_ie(WLAN_EID_SSID, ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len); - } - - /* sanitize map: [remove any old entries] */ - for (i = 0; i < SLSI_SCAN_SSID_MAP_MAX; i++) { - found = 0; - if (!sdev->ssid_map[i].ssid_len) - continue; - - /* We are connected to this hidden AP. So no need to check if this AP is present in scan results */ - if (is_connected && SLSI_ETHER_EQUAL(ndev_vif->sta.sta_bss->bssid, sdev->ssid_map[i].bssid) && - (sdev->ssid_map[i].band == band)) - continue; - - /* If this entry AP is found to be non-hidden, remove entry. */ - scan_result = ndev_vif->scan[scan_id].scan_results; - while (scan_result) { - if (SLSI_ETHER_EQUAL(sdev->ssid_map[i].bssid, scan_result->bssid) && - (sdev->ssid_map[i].band == scan_result->band)) { - /* AP is no more hidden. OR AP is hidden but did not - * receive probe resp. Go for expiry. - */ - if (!scan_result->hidden || (scan_result->hidden && !scan_result->probe_resp)) - sdev->ssid_map[i].age = SLSI_SCAN_SSID_MAP_EXPIRY_AGE; - else - found = 1; - break; - } - scan_result = scan_result->next; - } - - if (!found) { - sdev->ssid_map[i].age++; - if (sdev->ssid_map[i].age > SLSI_SCAN_SSID_MAP_EXPIRY_AGE) { - sdev->ssid_map[i].ssid_len = 0; - sdev->ssid_map[i].age = 0; - } - } - } - - scan_result = ndev_vif->scan[scan_id].scan_results; - /* update/add hidden bss with known ssid */ - while (scan_result) { - ssid_ie = NULL; - - if (scan_result->hidden) { - if (is_connected && SLSI_ETHER_EQUAL(ndev_vif->sta.sta_bss->bssid, scan_result->bssid) && - (scan_result->band == band)) { - ssid_ie = connected_ssid; - } else if (scan_result->probe_resp) { - mgmt = fapi_get_mgmt(scan_result->probe_resp); - ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, fapi_get_mgmtlen(scan_result->probe_resp) - (mgmt->u.beacon.variable - (u8 *)mgmt)); - } - } - - if (!ssid_ie) { - scan_result = scan_result->next; - continue; - } - - found = 0; - /* if this bss is in map, update map */ - for (i = 0; i < SLSI_SCAN_SSID_MAP_MAX; i++) { - if (!sdev->ssid_map[i].ssid_len) - continue; - if (SLSI_ETHER_EQUAL(scan_result->bssid, sdev->ssid_map[i].bssid) && - (scan_result->band == sdev->ssid_map[i].band)) { - sdev->ssid_map[i].ssid_len = ssid_ie[1]; - memcpy(sdev->ssid_map[i].ssid, &ssid_ie[2], ssid_ie[1]); - found = 1; - break; - } - } - if (!found) { - /* add a new entry in map */ - for (i = 0; i < SLSI_SCAN_SSID_MAP_MAX; i++) { - if (sdev->ssid_map[i].ssid_len) - continue; - SLSI_ETHER_COPY(sdev->ssid_map[i].bssid, scan_result->bssid); - sdev->ssid_map[i].age = 0; - sdev->ssid_map[i].ssid_len = ssid_ie[1]; - sdev->ssid_map[i].band = scan_result->band; - memcpy(sdev->ssid_map[i].ssid, &ssid_ie[2], ssid_ie[1]); - break; - } - } - scan_result = scan_result->next; - } -} - -void slsi_scan_complete(struct slsi_dev *sdev, struct net_device *dev, u16 scan_id, bool aborted) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *scan; - int count = 0; - int *result_count = NULL, max_count = 0; - struct cfg80211_scan_info info = {.aborted = aborted}; - int scan_results_count = 0; - int more_than_max_count = 0; - - if (WARN_ON(scan_id >= SLSI_SCAN_MAX)) - return; - - if (scan_id == SLSI_SCAN_HW_ID && !ndev_vif->scan[scan_id].scan_req) - return; - - if (WARN_ON(scan_id == SLSI_SCAN_SCHED_ID && !ndev_vif->scan[scan_id].sched_req)) - return; - - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - slsi_scan_update_ssid_map(sdev, dev, scan_id); - result_count = &count; - max_count = slsi_dev_get_scan_result_count(); - } - scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], result_count); - while (scan) { - scan_results_count++; - /* skb freed inside slsi_rx_scan_pass_to_cfg80211 */ - slsi_rx_scan_pass_to_cfg80211(sdev, dev, scan); - - if ((SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) && (*result_count >= max_count)) { - more_than_max_count = 1; - slsi_purge_scan_results_locked(ndev_vif, scan_id); - break; - } - scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], result_count); - } - SLSI_INFO(sdev, "Scan count:%d APs\n", scan_results_count); - SLSI_NET_DBG3(dev, SLSI_MLME, "interface:%d, scan_id:%d,%s\n", ndev_vif->ifnum, scan_id, - more_than_max_count ? "Scan results overflow" : ""); - slsi_roam_channel_cache_prune(dev, SLSI_ROAMING_CHANNEL_CACHE_TIMEOUT); - - if (scan_id == SLSI_SCAN_HW_ID) { - if (SLSI_IS_VIF_INDEX_P2P(ndev_vif) && (!SLSI_IS_P2P_GROUP_STATE(sdev))) { - /* Check for unsync vif as it could be present during the cycle of social channel scan and listen */ - if (ndev_vif->activated) - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE); - else - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_NO_VIF); - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - cfg80211_scan_done(ndev_vif->scan[scan_id].scan_req, &info); -#else - cfg80211_scan_done(ndev_vif->scan[scan_id].scan_req, aborted); -#endif - - ndev_vif->scan[scan_id].scan_req = NULL; - ndev_vif->scan[scan_id].requeue_timeout_work = false; - } - - if (scan_id == SLSI_SCAN_SCHED_ID && scan_results_count > 0) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) - cfg80211_sched_scan_results(sdev->wiphy, ndev_vif->scan[scan_id].sched_req->reqid); -#else - cfg80211_sched_scan_results(sdev->wiphy); -#endif - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); -} - -int slsi_set_2g_auto_channel(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, - struct slsi_acs_selected_channels *acs_selected_channels, - struct slsi_acs_chan_info *ch_info) -{ - int i = 0, j = 0, avg_load, total_num_ap, total_rssi, adjacent_rssi; - bool all_bss_load = true, none_bss_load = true; - int min_avg_chan_utilization = INT_MAX, min_adjacent_rssi = INT_MAX; - int ch_idx_min_load = 0, ch_idx_min_rssi = 0; - int min_avg_chan_utilization_20 = INT_MAX, min_adjacent_rssi_20 = INT_MAX; - int ch_idx_min_load_20 = 0, ch_idx_min_rssi_20 = 0; - int ret = 0; - int ch_list_len = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_list_len; - - acs_selected_channels->ch_width = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_width; - acs_selected_channels->hw_mode = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode; - - SLSI_DBG3(sdev, SLSI_MLME, "ch_lis_len:%d\n", ch_list_len); - for (i = 0; i < ch_list_len; i++) { - if (!ch_info[i].chan) - continue; - adjacent_rssi = 0; /* Assuming ch_list is in sorted order. */ - for (j = -2; j <= 2; j++) - if (i + j >= 0 && i + j < ch_list_len) - adjacent_rssi += ch_info[i + j].rssi_factor; - ch_info[i].adj_rssi_factor = adjacent_rssi; - if (ch_info[i].num_bss_load_ap != 0) { - ch_info[i].avg_chan_utilization = ch_info[i].total_chan_utilization / - ch_info[i].num_bss_load_ap; - if (ch_info[i].avg_chan_utilization < min_avg_chan_utilization_20) { - min_avg_chan_utilization_20 = ch_info[i].avg_chan_utilization; - ch_idx_min_load_20 = i; - } else if (ch_info[i].avg_chan_utilization == min_avg_chan_utilization_20 && - ch_info[i].num_ap < ch_info[ch_idx_min_load_20].num_ap) { - ch_idx_min_load_20 = i; - } - none_bss_load = false; - } else { - SLSI_DBG3(sdev, SLSI_MLME, "BSS load IE not found\n"); - all_bss_load = false; - } - if (adjacent_rssi < min_adjacent_rssi_20) { - min_adjacent_rssi_20 = adjacent_rssi; - ch_idx_min_rssi_20 = i; - } else if (adjacent_rssi == min_adjacent_rssi_20 && - ch_info[i].num_ap < ch_info[ch_idx_min_rssi_20].num_ap) { - ch_idx_min_rssi_20 = i; - } - SLSI_DBG3(sdev, SLSI_MLME, "min rssi:%d min_rssi_idx:%d\n", min_adjacent_rssi_20, ch_idx_min_rssi_20); - SLSI_DBG3(sdev, SLSI_MLME, "num_ap:%d,chan:%d,total_util:%d,avg_util:%d,rssi_fac:%d,adj_rssi_fac:%d," - "bss_ap:%d\n", ch_info[i].num_ap, ch_info[i].chan, ch_info[i].total_chan_utilization, - ch_info[i].avg_chan_utilization, ch_info[i].rssi_factor, ch_info[i].adj_rssi_factor, - ch_info[i].num_bss_load_ap); - } - - if (acs_selected_channels->ch_width == 40) { - for (i = 0; i < ch_list_len; i++) { - if (i + 4 >= ch_list_len || !ch_info[i + 4].chan || !ch_info[i].chan) - continue; - avg_load = ch_info[i].avg_chan_utilization + ch_info[i + 4].avg_chan_utilization; - total_num_ap = ch_info[i].num_ap + ch_info[i + 4].num_ap; - total_rssi = ch_info[i].adj_rssi_factor + ch_info[i + 4].adj_rssi_factor; - - if (avg_load < min_avg_chan_utilization) { - min_avg_chan_utilization = avg_load; - ch_idx_min_load = i; - } else if (avg_load == min_avg_chan_utilization && - total_num_ap < ch_info[ch_idx_min_load].num_ap + - ch_info[ch_idx_min_load + 4].num_ap) { - ch_idx_min_load = i; - } - if (total_rssi < min_adjacent_rssi) { - min_adjacent_rssi = total_rssi; - ch_idx_min_rssi = i; - } else if (total_rssi == min_adjacent_rssi && - total_num_ap < ch_info[ch_idx_min_rssi].num_ap + - ch_info[ch_idx_min_rssi + 4].num_ap) { - ch_idx_min_rssi = i; - } - } - if (all_bss_load) { - acs_selected_channels->pri_channel = ch_info[ch_idx_min_load].chan; - acs_selected_channels->sec_channel = ch_info[ch_idx_min_load].chan + 4; - } else { - acs_selected_channels->pri_channel = ch_info[ch_idx_min_rssi].chan; - acs_selected_channels->sec_channel = ch_info[ch_idx_min_rssi].chan + 4; - } - - if (!acs_selected_channels->pri_channel) - acs_selected_channels->ch_width = 20; - } - - if (acs_selected_channels->ch_width == 20) { - if (all_bss_load) - acs_selected_channels->pri_channel = ch_info[ch_idx_min_load_20].chan; - else - acs_selected_channels->pri_channel = ch_info[ch_idx_min_rssi_20].chan; - } - return ret; -} - -int slsi_is_40mhz_5gchan(u8 pri_channel, u8 sec_channel) -{ - int slsi_40mhz_chan[12] = {38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159}; - int i; - - for (i = 0; i < 12; i++) { - if (pri_channel == slsi_40mhz_chan[i] - 2 && sec_channel == slsi_40mhz_chan[i] + 2) - return 1; - else if (pri_channel < slsi_40mhz_chan[i]) - return 0; - } - return 0; -} - -int slsi_is_80mhz_5gchan(u8 pri_channel, u8 last_channel) -{ - int slsi_80mhz_chan[6] = {42, 58, 106, 122, 138, 155}; - int i; - - for (i = 0; i < 6; i++) { - if (pri_channel == slsi_80mhz_chan[i] - 6 && last_channel == slsi_80mhz_chan[i] + 6) - return 1; - else if (pri_channel < slsi_80mhz_chan[i]) - return 0; - } - return 0; -} - -int slsi_set_5g_auto_channel(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, - struct slsi_acs_selected_channels *acs_selected_channels, - struct slsi_acs_chan_info *ch_info) -{ - int i = 0, avg_load, total_num_ap; - bool all_bss_load = true, none_bss_load = true; - int min_num_ap = INT_MAX, min_avg_chan_utilization = INT_MAX; - int ch_idx_min_load = 0, ch_idx_min_ap = 0; - int min_avg_chan_utilization_20 = INT_MAX, min_num_ap_20 = INT_MAX; - int ch_idx_min_load_20 = 0, ch_idx_min_ap_20 = 0; - int ret = 0; - int ch_list_len = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_list_len; - - acs_selected_channels->ch_width = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_width; - acs_selected_channels->hw_mode = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode; - - SLSI_DBG3(sdev, SLSI_MLME, "ch_lis_len:%d\n", ch_list_len); - for (i = 0; i < ch_list_len; i++) { - if (!ch_info[i].chan) - continue; - if (ch_info[i].num_bss_load_ap != 0) { - ch_info[i].avg_chan_utilization = ch_info[i].total_chan_utilization / - ch_info[i].num_bss_load_ap; - if (ch_info[i].avg_chan_utilization < min_avg_chan_utilization_20) { - min_avg_chan_utilization_20 = ch_info[i].avg_chan_utilization; - ch_idx_min_load_20 = i; - } else if (ch_info[i].avg_chan_utilization == min_avg_chan_utilization_20 && - ch_info[i].num_ap < ch_info[ch_idx_min_load_20].num_ap) { - ch_idx_min_load_20 = i; - } - none_bss_load = false; - } else { - if (ch_info[i].num_ap < min_num_ap_20) { - min_num_ap_20 = ch_info[i].num_ap; - ch_idx_min_ap_20 = i; - } - SLSI_DBG3(sdev, SLSI_MLME, "BSS load IE not found\n"); - ch_info[i].avg_chan_utilization = 128; - all_bss_load = false; - } - SLSI_DBG3(sdev, SLSI_MLME, "num_ap:%d chan:%d, total_chan_util:%d, avg_chan_util:%d, bss_load_ap:%d\n", - ch_info[i].num_ap, ch_info[i].chan, ch_info[i].total_chan_utilization, - ch_info[i].avg_chan_utilization, ch_info[i].num_bss_load_ap); - } - - if (acs_selected_channels->ch_width == 80) { - for (i = 0; i < ch_list_len; i++) { - if (i + 3 >= ch_list_len) - continue; - if (!ch_info[i].chan || !ch_info[i + 1].chan || !ch_info[i + 2].chan || !ch_info[i + 3].chan) - continue; - if (slsi_is_80mhz_5gchan(ch_info[i].chan, ch_info[i + 3].chan)) { - avg_load = ch_info[i].avg_chan_utilization + ch_info[i + 1].avg_chan_utilization + - ch_info[i + 2].avg_chan_utilization + ch_info[i + 3].avg_chan_utilization; - total_num_ap = ch_info[i].num_ap + ch_info[i + 1].num_ap + ch_info[i + 2].num_ap + - ch_info[i + 3].num_ap; - if (avg_load < min_avg_chan_utilization) { - min_avg_chan_utilization = avg_load; - ch_idx_min_load = i; - } else if (avg_load == min_avg_chan_utilization && total_num_ap < - (ch_info[ch_idx_min_load].num_ap + ch_info[ch_idx_min_load + 1].num_ap + - ch_info[ch_idx_min_load + 2].num_ap + - ch_info[ch_idx_min_load + 3].num_ap)) { - ch_idx_min_load = i; - } - if (total_num_ap < min_num_ap) { - min_num_ap = total_num_ap; - ch_idx_min_ap = i; - } - } - } - if (all_bss_load || min_avg_chan_utilization <= 512) { - acs_selected_channels->pri_channel = ch_info[ch_idx_min_load].chan; - acs_selected_channels->vht_seg0_center_ch = ch_info[ch_idx_min_load].chan + 6; - } else if (none_bss_load || min_avg_chan_utilization > 512) { - acs_selected_channels->pri_channel = ch_info[ch_idx_min_ap].chan; - acs_selected_channels->vht_seg0_center_ch = ch_info[ch_idx_min_ap].chan + 6; - } - - if (!acs_selected_channels->pri_channel) - acs_selected_channels->ch_width = 40; - } - - if (acs_selected_channels->ch_width == 40) { - for (i = 0; i < ch_list_len; i++) { - if (!ch_info[i].chan || i + 1 >= ch_list_len || !ch_info[i + 1].chan) - continue; - if (slsi_is_40mhz_5gchan(ch_info[i].chan, ch_info[i + 1].chan)) { - avg_load = ch_info[i].avg_chan_utilization + ch_info[i + 1].avg_chan_utilization; - total_num_ap = ch_info[i].num_ap + ch_info[i + 1].num_ap; - if (avg_load < min_avg_chan_utilization) { - min_avg_chan_utilization = avg_load; - ch_idx_min_load = i; - } else if (avg_load == min_avg_chan_utilization && total_num_ap < - ch_info[ch_idx_min_load].num_ap + ch_info[ch_idx_min_load + 1].num_ap) { - ch_idx_min_load = i; - } - if (total_num_ap < min_num_ap) { - min_num_ap = total_num_ap; - ch_idx_min_ap = i; - } - } - } - if (all_bss_load || min_avg_chan_utilization <= 256) { - acs_selected_channels->pri_channel = ch_info[ch_idx_min_load].chan; - acs_selected_channels->sec_channel = ch_info[ch_idx_min_load + 1].chan; - } else if (none_bss_load || min_avg_chan_utilization > 256) { - acs_selected_channels->pri_channel = ch_info[ch_idx_min_ap].chan; - acs_selected_channels->sec_channel = ch_info[ch_idx_min_ap + 1].chan; - } - - if (!acs_selected_channels->pri_channel) - acs_selected_channels->ch_width = 20; - } - - if (acs_selected_channels->ch_width == 20) { - if (all_bss_load || min_avg_chan_utilization_20 < 128) - acs_selected_channels->pri_channel = ch_info[ch_idx_min_load_20].chan; - else if (none_bss_load || min_avg_chan_utilization_20 >= 128) - acs_selected_channels->pri_channel = ch_info[ch_idx_min_ap_20].chan; - } - return ret; -} - -int slsi_acs_get_rssi_factor(struct slsi_dev *sdev, int rssi, int ch_util) -{ - int frac_pow_val[10] = {10, 12, 15, 19, 25, 31, 39, 50, 63, 79}; - int res = 1; - int i; - - if (rssi < 0) - rssi = 0 - rssi; - else - return INT_MAX; - for (i = 0; i < rssi / 10; i++) - res *= 10; - res = (10000000 * ch_util / res) / frac_pow_val[rssi % 10]; - - SLSI_DBG3(sdev, SLSI_MLME, "ch_util:%d\n", ch_util); - return res; -} - -struct slsi_acs_chan_info *slsi_acs_scan_results(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, u16 scan_id) -{ - struct sk_buff *scan_res; - struct sk_buff *unique_scan; - struct sk_buff_head unique_scan_results; - struct slsi_acs_chan_info *ch_info = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->acs_chan_info; - - SLSI_DBG3(sdev, SLSI_MLME, "Received acs_results\n"); - skb_queue_head_init(&unique_scan_results); - SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex); - scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL); - - while (scan_res) { - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(scan_res); - size_t mgmt_len = fapi_get_mgmtlen(scan_res); - struct ieee80211_channel *scan_channel; - int idx = 0; - const u8 *ie_data; - const u8 *ie; - int ie_len; - int ch_util = 128; - /* ieee80211_mgmt structure is similar for Probe Response and Beacons */ - size_t ies_len = mgmt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - /* make sure this BSSID has not already been used */ - skb_queue_walk(&unique_scan_results, unique_scan) { - struct ieee80211_mgmt *unique_mgmt = fapi_get_mgmt(unique_scan); - - if (compare_ether_addr(mgmt->bssid, unique_mgmt->bssid) == 0) - goto next_scan; - } - slsi_skb_queue_head(&unique_scan_results, scan_res); - scan_channel = slsi_find_scan_channel(sdev, mgmt, mgmt_len, - fapi_get_u16(scan_res, u.mlme_scan_ind.channel_frequency) / 2); - if (!scan_channel) - goto next_scan; - SLSI_DBG3(sdev, SLSI_MLME, "scan result (scan_id:%d, %pM, channel:%d, rssi:%d, ie_len = %zu)\n", - fapi_get_u16(scan_res, u.mlme_scan_ind.scan_id), - fapi_get_mgmt(scan_res)->bssid, scan_channel->hw_value, - fapi_get_s16(scan_res, u.mlme_scan_ind.rssi), - ies_len); - - idx = slsi_find_chan_idx(scan_channel->hw_value, ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode); - SLSI_DBG3(sdev, SLSI_MLME, "chan_idx:%d chan_value: %d\n", idx, ch_info[idx].chan); - - if ((idx < 0) || (idx > 24)) { - SLSI_DBG3(sdev, SLSI_MLME, "idx is not in range idx=%d\n", idx); - goto next_scan; - } - if (ch_info[idx].chan) { - ch_info[idx].num_ap += 1; - ie = cfg80211_find_ie(WLAN_EID_QBSS_LOAD, mgmt->u.beacon.variable, ies_len); - if (ie) { - ie_len = ie[1]; - ie_data = &ie[2]; - if (ie_len >= 3) { - ch_util = ie_data[2]; - ch_info[idx].num_bss_load_ap += 1; - ch_info[idx].total_chan_utilization += ch_util; - } - } - if (idx == scan_channel->hw_value - 1) { /*if 2.4GHZ channel */ - int res = 0; - - res = slsi_acs_get_rssi_factor(sdev, fapi_get_s16(scan_res, u.mlme_scan_ind.rssi), - ch_util); - ch_info[idx].rssi_factor += res; - SLSI_DBG3(sdev, SLSI_MLME, "ch_info[idx].rssi_factor:%d\n", ch_info[idx].rssi_factor); - } - } else { - goto next_scan; - } -next_scan: - scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], NULL); - } - SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex); - slsi_skb_queue_purge(&unique_scan_results); - return ch_info; -} - -void slsi_acs_scan_complete(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, u16 scan_id) -{ - struct slsi_acs_selected_channels acs_selected_channels; - struct slsi_acs_chan_info *ch_info; - int r = 0; - - memset(&acs_selected_channels, 0, sizeof(acs_selected_channels)); - ch_info = slsi_acs_scan_results(sdev, ndev_vif, scan_id); - if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode == SLSI_ACS_MODE_IEEE80211A) - r = slsi_set_5g_auto_channel(sdev, ndev_vif, &acs_selected_channels, ch_info); - else if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode == SLSI_ACS_MODE_IEEE80211B || - ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode == SLSI_ACS_MODE_IEEE80211G) - r = slsi_set_2g_auto_channel(sdev, ndev_vif, &acs_selected_channels, ch_info); - else - r = -EINVAL; - if (!r) { - r = slsi_send_acs_event(sdev, acs_selected_channels); - if (r != 0) - SLSI_ERR(sdev, "Could not send ACS vendor event up\n"); - } else { - SLSI_ERR(sdev, "set_auto_channel failed: %d\n", r); - } - sdev->acs_channel_switched = true; - kfree(ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request); - if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request) - ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request = NULL; -} - -void slsi_rx_scan_done_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 scan_id = fapi_get_u16(skb, u.mlme_scan_done_ind.scan_id); - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_MUTEX_LOCK(ndev_vif->scan_mutex); - SLSI_NET_DBG3(dev, SLSI_GSCAN, "slsi_rx_scan_done_ind Received scan_id:%#x\n", scan_id); - -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - if (slsi_is_gscan_id(scan_id)) { - SLSI_NET_DBG3(dev, SLSI_GSCAN, "scan_id:%#x\n", scan_id); - - slsi_gscan_handle_scan_result(sdev, dev, skb, scan_id, true); - - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return; - } -#endif - scan_id = (scan_id & 0xFF); - - if (scan_id == SLSI_SCAN_HW_ID && (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req || - ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request)) - cancel_delayed_work(&ndev_vif->scan_timeout_work); - if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request) - slsi_acs_scan_complete(sdev, ndev_vif, scan_id); - else - slsi_scan_complete(sdev, dev, scan_id, false); - - SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_channel_switched_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 freq = 0; - int width; - int primary_chan_pos; - u16 temp_chan_info; - struct cfg80211_chan_def chandef; - u16 cf1 = 0; - struct netdev_vif *ndev_vif = netdev_priv(dev); - - temp_chan_info = fapi_get_u16(skb, u.mlme_channel_switched_ind.channel_information); - cf1 = fapi_get_u16(skb, u.mlme_channel_switched_ind.channel_frequency); - cf1 = cf1 / 2; - - primary_chan_pos = (temp_chan_info >> 8); - width = (temp_chan_info & 0x00FF); - - /* If width is 80MHz/40MHz then do frequency calculation, else store as it is */ - if (width == 40) - freq = cf1 + (primary_chan_pos * 20) - 10; - else if (width == 80) - freq = cf1 + (primary_chan_pos * 20) - 30; - else - freq = cf1; - - if (width == 20) - width = NL80211_CHAN_WIDTH_20; - else if (width == 40) - width = NL80211_CHAN_WIDTH_40; - else if (width == 80) - width = NL80211_CHAN_WIDTH_80; - else if (width == 160) - width = NL80211_CHAN_WIDTH_160; - - chandef.chan = ieee80211_get_channel(sdev->wiphy, freq); - chandef.width = width; - chandef.center_freq1 = cf1; - chandef.center_freq2 = 0; - - ndev_vif->ap.channel_freq = freq; /* updated for GETSTAINFO */ - ndev_vif->chan = chandef.chan; - - cfg80211_ch_switch_notify(dev, &chandef); - slsi_kfree_skb(skb); -} - -void __slsi_rx_blockack_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - - SLSI_NET_DBG1(dev, SLSI_MLME, "ma_blockack_ind(vif:%d, peer_qsta_address:%pM, parameter_set:%d, sequence_number:%d, reason_code:%d, direction:%d)\n", - fapi_get_vif(skb), - fapi_get_buff(skb, u.ma_blockack_ind.peer_qsta_address), - fapi_get_u16(skb, u.ma_blockack_ind.blockack_parameter_set), - fapi_get_u16(skb, u.ma_blockack_ind.sequence_number), - fapi_get_u16(skb, u.ma_blockack_ind.reason_code), - fapi_get_u16(skb, u.ma_blockack_ind.direction)); - - peer = slsi_get_peer_from_mac(sdev, dev, fapi_get_buff(skb, u.ma_blockack_ind.peer_qsta_address)); - WARN_ON(!peer); - - if (peer) { - /* Buffering of frames before the mlme_connected_ind */ - if ((ndev_vif->vif_type == FAPI_VIFTYPE_AP) && (peer->connected_state == SLSI_STA_CONN_STATE_CONNECTING)) { - SLSI_DBG3(sdev, SLSI_MLME, "Buffering MA-BlockAck.Indication\n"); - slsi_skb_queue_tail(&peer->buffered_frames, skb); - return; - } - slsi_handle_blockack( - dev, - peer, - fapi_get_vif(skb), - fapi_get_buff(skb, u.ma_blockack_ind.peer_qsta_address), - fapi_get_u16(skb, u.ma_blockack_ind.blockack_parameter_set), - fapi_get_u16(skb, u.ma_blockack_ind.sequence_number), - fapi_get_u16(skb, u.ma_blockack_ind.reason_code), - fapi_get_u16(skb, u.ma_blockack_ind.direction) - ); - } - - slsi_kfree_skb(skb); -} - -void slsi_rx_blockack_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - __slsi_rx_blockack_ind(sdev, dev, skb); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -static bool get_wmm_ie_from_resp_ie(struct slsi_dev *sdev, struct net_device *dev, u8 *resp_ie, size_t resp_ie_len, const u8 **wmm_elem, size_t *wmm_elem_len) -{ - struct ieee80211_vendor_ie *ie; - - SLSI_UNUSED_PARAMETER(sdev); - - if (!resp_ie) { - SLSI_NET_ERR(dev, "Received invalid pointer to the ie's of the association response\n"); - return false; - } - - *wmm_elem = resp_ie; - while (*wmm_elem && (*wmm_elem - resp_ie < resp_ie_len)) { - /* parse response ie elements and return the wmm ie */ - *wmm_elem = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WMM, *wmm_elem, - resp_ie_len - (*wmm_elem - resp_ie)); - /* re-assoc-res can contain wmm parameter IE and wmm TSPEC IE. - * we want wmm parameter Element) - */ - if (*wmm_elem && (*wmm_elem)[1] > 6 && (*wmm_elem)[6] == WMM_OUI_SUBTYPE_PARAMETER_ELEMENT) - break; - if (*wmm_elem) - *wmm_elem += (*wmm_elem)[1]; - } - - if (!(*wmm_elem)) { - SLSI_NET_DBG2(dev, SLSI_MLME, "No WMM IE\n"); - return false; - } - ie = (struct ieee80211_vendor_ie *)*wmm_elem; - *wmm_elem_len = ie->len + 2; - - SLSI_NET_DBG3(dev, SLSI_MLME, "WMM IE received and parsed successfully\n"); - return true; -} - -static bool sta_wmm_update_uapsd(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, u8 *assoc_req_ie, size_t assoc_req_ie_len) -{ - const u8 *wmm_information_ie; - - if (!assoc_req_ie) { - SLSI_NET_ERR(dev, "null reference to IE\n"); - return false; - } - - wmm_information_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WMM, assoc_req_ie, assoc_req_ie_len); - if (!wmm_information_ie) { - SLSI_NET_DBG1(dev, SLSI_MLME, "no WMM IE\n"); - return false; - } - - peer->uapsd = wmm_information_ie[8]; - SLSI_NET_DBG1(dev, SLSI_MLME, "peer->uapsd = 0x%x\n", peer->uapsd); - return true; -} - -static bool sta_wmm_update_wmm_ac_ies(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer, - u8 *assoc_rsp_ie, size_t assoc_rsp_ie_len) -{ - size_t left; - const u8 *pos; - const u8 *wmm_elem = NULL; - size_t wmm_elem_len = 0; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_wmm_ac *wmm_ac = &ndev_vif->sta.wmm_ac[0]; - - if (!get_wmm_ie_from_resp_ie(sdev, dev, assoc_rsp_ie, assoc_rsp_ie_len, &wmm_elem, &wmm_elem_len)) { - SLSI_NET_DBG1(dev, SLSI_MLME, "No WMM IE received\n"); - return false; - } - - if (wmm_elem_len < 10 || wmm_elem[7] /* version */ != 1) { - SLSI_NET_WARN(dev, "Invalid WMM IE: wmm_elem_len=%lu, wmm_elem[7]=%d\n", (unsigned long int)wmm_elem_len, (int)wmm_elem[7]); - return false; - } - - pos = wmm_elem + 10; - left = wmm_elem_len - 10; - - for (; left >= 4; left -= 4, pos += 4) { - int aci = (pos[0] >> 5) & 0x03; - int acm = (pos[0] >> 4) & 0x01; - - memcpy(wmm_ac, pos, sizeof(struct slsi_wmm_ac)); - - switch (aci) { - case 1: /* AC_BK */ - if (acm) - peer->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ - break; - case 2: /* AC_VI */ - if (acm) - peer->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ - break; - case 3: /* AC_VO */ - if (acm) - peer->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ - break; - case 0: /* AC_BE */ - default: - if (acm) - peer->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ - break; - } - wmm_ac++; - } - - SLSI_NET_DBG3(dev, SLSI_MLME, "WMM ies have been updated successfully\n"); - return true; -} - -#ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD -enum slsi_wlan_vendor_attr_roam_auth { - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, - SLSI_WLAN_VENDOR_ATTR_ROAM_BEACON_IE, - /* keep last */ - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST, - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX = - SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1 -}; - -int slsi_send_roam_vendor_event(struct slsi_dev *sdev, const u8 *bssid, - const u8 *req_ie, u32 req_ie_len, const u8 *resp_ie, u32 resp_ie_len, - const u8 *beacon_ie, u32 beacon_ie_len, bool authorized) -{ - bool is_secured_bss; - struct sk_buff *skb = NULL; - u8 err = 0; - - is_secured_bss = cfg80211_find_ie(WLAN_EID_RSN, req_ie, req_ie_len) || - cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, req_ie, req_ie_len); - - SLSI_DBG2(sdev, SLSI_MLME, "authorized:%d, is_secured_bss:%d\n", authorized, is_secured_bss); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, - SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH, GFP_KERNEL); -#else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, - SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH, GFP_KERNEL); -#endif - if (!skb) { - SLSI_ERR_NODEV("Failed to allocate skb for VENDOR Roam event\n"); - return -ENOMEM; - } - - err |= nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, ETH_ALEN, bssid) ? BIT(1) : 0; - err |= nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, 1, &authorized) ? BIT(2) : 0; - err |= (req_ie && nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE, req_ie_len, req_ie)) ? BIT(3) : 0; - err |= (resp_ie && nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, resp_ie_len, resp_ie)) ? BIT(4) : 0; - err |= (beacon_ie && nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_BEACON_IE, beacon_ie_len, beacon_ie)) ? BIT(5) : 0; - if (err) { - SLSI_ERR_NODEV("Failed nla_put ,req_ie_len=%d,resp_ie_len=%d,beacon_ie_len=%d,condition_failed=%d\n", - req_ie_len, resp_ie_len, beacon_ie_len, err); - slsi_kfree_skb(skb); - return -EINVAL; - } - SLSI_DBG3_NODEV(SLSI_MLME, "Event: KEY_MGMT_ROAM_AUTH(%d)\n", SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH); - cfg80211_vendor_event(skb, GFP_KERNEL); - return 0; -} -#endif /* offload */ - -void slsi_rx_roamed_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - struct slsi_peer *peer; - u16 temporal_keys_required = fapi_get_u16(skb, u.mlme_roamed_ind.temporal_keys_required); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - enum ieee80211_privacy bss_privacy; -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) - struct cfg80211_roam_info roam_info = {}; -#endif - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_roamed_ind(vif:%d) Roaming to %pM\n", - fapi_get_vif(skb), - mgmt->bssid); - - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!peer)) - goto exit; - - if (WARN_ON(!ndev_vif->sta.sta_bss)) - goto exit; - - slsi_rx_ba_stop_all(dev, peer); - - SLSI_ETHER_COPY(peer->address, mgmt->bssid); - - if (ndev_vif->sta.mlme_scan_ind_skb) { - /* saved skb [mlme_scan_ind] freed inside slsi_rx_scan_pass_to_cfg80211 */ - slsi_rx_scan_pass_to_cfg80211(sdev, dev, ndev_vif->sta.mlme_scan_ind_skb); - ndev_vif->sta.mlme_scan_ind_skb = NULL; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - if (ndev_vif->sta.sta_bss->capability & WLAN_CAPABILITY_PRIVACY) - bss_privacy = IEEE80211_PRIVACY_ON; - else - bss_privacy = IEEE80211_PRIVACY_OFF; -#endif - - slsi_cfg80211_put_bss(sdev->wiphy, ndev_vif->sta.sta_bss); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - ndev_vif->sta.sta_bss = cfg80211_get_bss(sdev->wiphy, NULL, peer->address, NULL, 0, - IEEE80211_BSS_TYPE_ANY, bss_privacy); -#else - ndev_vif->sta.sta_bss = cfg80211_get_bss(sdev->wiphy, NULL, peer->address, NULL, 0, 0, 0); -#endif - - if (!ndev_vif->sta.sta_bss || !ndev_vif->sta.roam_mlme_procedure_started_ind) { - if (!ndev_vif->sta.sta_bss) - SLSI_INFO(sdev, "BSS not updated in cfg80211\n"); - if (!ndev_vif->sta.roam_mlme_procedure_started_ind) - SLSI_INFO(sdev, "procedure-started-ind not received before roamed-ind\n"); - netif_carrier_off(dev); - slsi_mlme_disconnect(sdev, dev, peer->address, 0, true); - slsi_handle_disconnect(sdev, dev, peer->address, 0, NULL, 0); - } else { - u8 *assoc_ie = NULL; - int assoc_ie_len = 0; - u8 *assoc_rsp_ie = NULL; - int assoc_rsp_ie_len = 0; - - slsi_peer_reset_stats(sdev, dev, peer); - slsi_peer_update_assoc_req(sdev, dev, peer, ndev_vif->sta.roam_mlme_procedure_started_ind); - slsi_peer_update_assoc_rsp(sdev, dev, peer, skb); - - /* skb is consumed by slsi_peer_update_assoc_rsp. So do not access this anymore. */ - skb = NULL; - - if (peer->assoc_ie) { - assoc_ie = peer->assoc_ie->data; - assoc_ie_len = peer->assoc_ie->len; - } - - if (peer->assoc_resp_ie) { - assoc_rsp_ie = peer->assoc_resp_ie->data; - assoc_rsp_ie_len = peer->assoc_resp_ie->len; - } - - /* this is the right place to initialize the bitmasks for - * acm bit and tspec establishment - */ - peer->wmm_acm = 0; - peer->tspec_established = 0; - peer->uapsd = 0; - - /* update the uapsd bitmask according to the bit values - * in wmm information element of association request - */ - if (!sta_wmm_update_uapsd(sdev, dev, peer, assoc_ie, assoc_ie_len)) - SLSI_NET_DBG1(dev, SLSI_MLME, "Fail to update WMM uapsd\n"); - - /* update the acm bitmask according to the acm bit values that - * are included in wmm ie element of association response - */ - if (!sta_wmm_update_wmm_ac_ies(sdev, dev, peer, assoc_rsp_ie, assoc_rsp_ie_len)) - SLSI_NET_DBG1(dev, SLSI_MLME, "Fail to update WMM AC ies\n"); - - ndev_vif->sta.roam_mlme_procedure_started_ind = NULL; - - if (temporal_keys_required) { - peer->pairwise_key_set = 0; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DOING_KEY_CONFIG); - } - - WARN_ON(assoc_ie_len && !assoc_ie); - WARN_ON(assoc_rsp_ie_len && !assoc_rsp_ie); - - SLSI_NET_DBG3(dev, SLSI_MLME, "cfg80211_roamed()\n"); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) - /* cfg80211 does not require bss pointer in roam_info. - * If bss pointer is given in roam_info, cfg80211 bss - * data base goes bad and results in random panic. - */ - roam_info.channel = ndev_vif->sta.sta_bss->channel; - roam_info.bssid = peer->address; - roam_info.req_ie = assoc_ie; - roam_info.req_ie_len = assoc_ie_len; - roam_info.resp_ie = assoc_rsp_ie; - roam_info.resp_ie_len = assoc_rsp_ie_len; - cfg80211_roamed(dev, &roam_info, GFP_KERNEL); -#else - cfg80211_roamed(dev, - ndev_vif->sta.sta_bss->channel, - peer->address, - assoc_ie, - assoc_ie_len, - assoc_rsp_ie, - assoc_rsp_ie_len, - GFP_KERNEL); -#endif -#ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD - if (slsi_send_roam_vendor_event(sdev, peer->address, assoc_ie, assoc_ie_len, - assoc_rsp_ie, assoc_rsp_ie_len, - ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len, - !temporal_keys_required) != 0) { - SLSI_NET_ERR(dev, "Could not send Roam vendor event up"); - } -#endif - SLSI_NET_DBG3(dev, SLSI_MLME, "cfg80211_roamed() Done\n"); - - ndev_vif->sta.roam_in_progress = false; - ndev_vif->chan = ndev_vif->sta.sta_bss->channel; -#if !defined SLSI_TEST_DEV && defined CONFIG_ANDROID - SLSI_NET_DBG1(dev, SLSI_MLME, "Taking a wakelock for DHCP to finish after roaming\n"); - wake_lock_timeout(&sdev->wlan_wl_roam, msecs_to_jiffies(10 * 1000)); -#ifdef CONFIG_SCSC_WIFILOGGER - SCSC_WLOG_WAKELOCK(WLOG_NORMAL, WL_TAKEN, "wlan_wl_roam", WL_REASON_ROAM); -#endif -#endif - - if (!temporal_keys_required) { - slsi_mlme_roamed_resp(sdev, dev); - cac_update_roam_traffic_params(sdev, dev); - } else { - ndev_vif->sta.resp_id = MLME_ROAMED_RES; - } - } - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_roam_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; - - SLSI_UNUSED_PARAMETER(sdev); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_roam_ind(vif:%d, aid:0, result:0x%04x )\n", - fapi_get_vif(skb), - fapi_get_u16(skb, u.mlme_roam_ind.result_code)); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit_with_lock; - } - - if (WARN(ndev_vif->vif_type != FAPI_VIFTYPE_STATION, "Not a Station VIF\n")) - goto exit_with_lock; - - if (fapi_get_u16(skb, u.mlme_roam_ind.result_code) != FAPI_RESULTCODE_HOST_REQUEST_SUCCESS) - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -static void slsi_tdls_event_discovered(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 tdls_event = fapi_get_u16(skb, u.mlme_tdls_peer_ind.tdls_event); - u16 peer_index = fapi_get_u16(skb, u.mlme_tdls_peer_ind.peer_index); - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - int len = fapi_get_mgmtlen(skb); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_INFO(sdev, "\n"); - - if (len != 0) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_rx_mgmt(&ndev_vif->wdev, ndev_vif->chan->center_freq, 0, (const u8 *)mgmt, len, GFP_ATOMIC); -#else - cfg80211_rx_mgmt(dev, ndev_vif->chan->center_freq, 0, (const u8 *)mgmt, len, GFP_ATOMIC); -#endif - /* Handling MLME-TDLS-PEER.response */ - slsi_mlme_tdls_peer_resp(sdev, dev, peer_index, tdls_event); - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - - slsi_kfree_skb(skb); -} - -static void slsi_tdls_event_connected(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct slsi_peer *peer = NULL; - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 peer_index = fapi_get_u16(skb, u.mlme_tdls_peer_ind.peer_index); - u16 tdls_event = fapi_get_u16(skb, u.mlme_tdls_peer_ind.tdls_event); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - ndev_vif->sta.tdls_enabled = true; - - SLSI_INFO(sdev, "(vif:%d, peer_index:%d mac[%pM])\n", - fapi_get_vif(skb), peer_index, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address)); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit_with_lock; - } - - if (WARN(ndev_vif->vif_type != FAPI_VIFTYPE_STATION, "STA VIF")) - goto exit_with_lock; - - if (peer_index < SLSI_TDLS_PEER_INDEX_MIN || peer_index > SLSI_TDLS_PEER_INDEX_MAX) { - SLSI_NET_ERR(dev, "Received incorrect peer_index: %d\n", peer_index); - goto exit_with_lock; - } - - slsi_spinlock_lock(&ndev_vif->peer_lock); - /* Check for MAX client */ - if ((ndev_vif->sta.tdls_peer_sta_records) + 1 > SLSI_TDLS_PEER_CONNECTIONS_MAX) { - SLSI_NET_ERR(dev, "MAX TDLS peer limit reached. Ignore ind for peer_index:%d\n", peer_index); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - goto exit_with_lock; - } - - peer = slsi_peer_add(sdev, dev, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address), peer_index); - - if (!peer) { - SLSI_NET_ERR(dev, "Peer NOT Created\n"); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - goto exit_with_lock; - } - - /* QoS is mandatory for TDLS - enable QoS for TDLS peer by default */ - peer->qos_enabled = true; - - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - - /* Move TDLS packets from STA_Q to TDLS_Q */ - slsi_tdls_move_packets(sdev, dev, ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET], peer, true); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - - /* Handling MLME-TDLS-PEER.response */ - slsi_mlme_tdls_peer_resp(sdev, dev, peer_index, tdls_event); - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -static void slsi_tdls_event_disconnected(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct slsi_peer *peer = NULL; - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 pid = fapi_get_u16(skb, u.mlme_tdls_peer_ind.peer_index); - u16 tdls_event = fapi_get_u16(skb, u.mlme_tdls_peer_ind.tdls_event); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (WARN_ON(!dev)) - goto exit; - - SLSI_INFO(sdev, "(vif:%d, MAC:%pM)\n", ndev_vif->ifnum, - fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address)); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit; - } - - slsi_spinlock_lock(&ndev_vif->peer_lock); - peer = slsi_get_peer_from_mac(sdev, dev, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address)); - - if (!peer || (peer->aid == 0)) { - WARN_ON(!peer || (peer->aid == 0)); - SLSI_NET_DBG1(dev, SLSI_MLME, "peer NOT found by MAC address\n"); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - goto exit; - } - - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED); - - /* Move TDLS packets from TDLS_Q to STA_Q */ - slsi_tdls_move_packets(sdev, dev, ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET], peer, false); - - slsi_peer_remove(sdev, dev, peer); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - - slsi_mlme_tdls_peer_resp(sdev, dev, pid, tdls_event); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -/* Handling for MLME-TDLS-PEER.indication - */ -void slsi_tdls_peer_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 tdls_event = fapi_get_u16(skb, u.mlme_tdls_peer_ind.tdls_event); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_tdls_peer_ind tdls_event: %d\n", tdls_event); - - switch (tdls_event) { - case FAPI_TDLSEVENT_CONNECTED: - slsi_tdls_event_connected(sdev, dev, skb); - break; - case FAPI_TDLSEVENT_DISCONNECTED: - slsi_tdls_event_disconnected(sdev, dev, skb); - break; - case FAPI_TDLSEVENT_DISCOVERED: - slsi_tdls_event_discovered(sdev, dev, skb); - break; - default: - WARN_ON((tdls_event == 0) || (tdls_event > 4)); - slsi_kfree_skb(skb); - break; - } -} - -/* Retrieve any buffered frame before connected_ind and pass them up. */ -void slsi_rx_buffered_frames(struct slsi_dev *sdev, struct net_device *dev, struct slsi_peer *peer) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *buff_frame = NULL; - - WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)); - if (WARN(!peer, "Peer is NULL")) - return; - WARN(peer->connected_state == SLSI_STA_CONN_STATE_CONNECTING, "Wrong state"); - - SLSI_NET_DBG2(dev, SLSI_MLME, "Processing buffered RX frames received before mlme_connected_ind for (vif:%d, aid:%d)\n", - ndev_vif->ifnum, peer->aid); - buff_frame = slsi_skb_dequeue(&peer->buffered_frames); - while (buff_frame) { - slsi_debug_frame(sdev, dev, buff_frame, "RX_BUFFERED"); - switch (fapi_get_sigid(buff_frame)) { - case MA_BLOCKACK_IND: - SLSI_NET_DBG2(dev, SLSI_MLME, "Transferring buffered MA_BLOCKACK_IND frame"); - __slsi_rx_blockack_ind(sdev, dev, buff_frame); - break; - default: - SLSI_NET_WARN(dev, "Unexpected Data: 0x%.4x\n", fapi_get_sigid(buff_frame)); - slsi_kfree_skb(buff_frame); - break; - } - buff_frame = slsi_skb_dequeue(&peer->buffered_frames); - } -} - -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG -void slsi_rx_synchronised_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - const u8 *connecting_ssid = NULL; - struct cfg80211_external_auth_params auth_request; - int r; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_NET_DBG1(dev, SLSI_MLME, "Received slsi_rx_synchronised_ind\n"); - if (ndev_vif->sta.sta_bss->ies->len) - connecting_ssid = cfg80211_find_ie(WLAN_EID_SSID, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - - auth_request.action = NL80211_EXTERNAL_AUTH_START; - memcpy(auth_request.bssid, ndev_vif->sta.sta_bss->bssid, ETH_ALEN); - if (connecting_ssid && (connecting_ssid[1] > 0)) { - memcpy(auth_request.ssid.ssid, &connecting_ssid[2], connecting_ssid[1]); - auth_request.ssid.ssid_len = connecting_ssid[1]; - } - auth_request.key_mgmt_suite = ndev_vif->sta.crypto.akm_suites[0]; - r = cfg80211_external_auth_request(dev, &auth_request, GFP_KERNEL); - if (r) - SLSI_NET_DBG1(dev, SLSI_MLME, "cfg80211_external_auth_request failed"); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} -#endif - -void slsi_rx_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = NULL; - u16 aid = fapi_get_u16(skb, u.mlme_connected_ind.association_identifier); - - /* For AP mode, peer_index value is equivalent to aid(association_index) value */ - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connected_ind(vif:%d, peer_index:%d)\n", - fapi_get_vif(skb), - aid); - SLSI_INFO(sdev, "Received Association Response\n"); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit_with_lock; - } - - if (WARN(ndev_vif->vif_type == FAPI_VIFTYPE_STATION, "STA VIF and Not Roaming")) - goto exit_with_lock; - - switch (ndev_vif->vif_type) { - case FAPI_VIFTYPE_AP: - { - if (aid < SLSI_PEER_INDEX_MIN || aid > SLSI_PEER_INDEX_MAX) { - SLSI_NET_ERR(dev, "Received incorrect peer_index: %d\n", aid); - goto exit_with_lock; - } - - peer = slsi_get_peer_from_qs(sdev, dev, aid - 1); - if (!peer) { - SLSI_NET_ERR(dev, "Peer (aid:%d) Not Found - Disconnect peer\n", aid); - goto exit_with_lock; - } - - cfg80211_new_sta(dev, peer->address, &peer->sinfo, GFP_KERNEL); - - if (ndev_vif->ap.privacy) { - peer->connected_state = SLSI_STA_CONN_STATE_DOING_KEY_CONFIG; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DOING_KEY_CONFIG); - } else { - peer->connected_state = SLSI_STA_CONN_STATE_CONNECTED; - slsi_mlme_connected_resp(sdev, dev, aid); - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - } - slsi_rx_buffered_frames(sdev, dev, peer); - break; - } - - default: - SLSI_NET_WARN(dev, "mlme_connected_ind(vif:%d, unexpected vif type:%d)\n", fapi_get_vif(skb), ndev_vif->vif_type); - break; - } -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_reassoc_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; - struct slsi_peer *peer = NULL; - u8 *assoc_ie = NULL; - int assoc_ie_len = 0; - u8 *reassoc_rsp_ie = NULL; - int reassoc_rsp_ie_len = 0; - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_reassoc_ind(vif:%d, result:0x%04x)\n", - fapi_get_vif(skb), - fapi_get_u16(skb, u.mlme_reassociate_ind.result_code)); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit_with_lock; - } - - if (WARN(ndev_vif->vif_type != FAPI_VIFTYPE_STATION, "Not a Station VIF\n")) - goto exit_with_lock; - - peer = slsi_get_peer_from_qs(sdev, dev, 0); - if (WARN_ON(!peer)) { - SLSI_NET_ERR(dev, "PEER Not found\n"); - goto exit_with_lock; - } - - if (fapi_get_u16(skb, u.mlme_reassociate_ind.result_code) != FAPI_RESULTCODE_SUCCESS) { - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - slsi_rx_ba_stop_all(dev, peer); - } else { - peer->pairwise_key_set = 0; - - if (peer->assoc_ie) { - assoc_ie = peer->assoc_ie->data; - assoc_ie_len = peer->assoc_ie->len; - WARN_ON(assoc_ie_len && !assoc_ie); - } - - slsi_peer_reset_stats(sdev, dev, peer); - - peer->sinfo.assoc_req_ies = assoc_ie; - peer->sinfo.assoc_req_ies_len = assoc_ie_len; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) - peer->sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; -#endif - slsi_peer_update_assoc_rsp(sdev, dev, peer, skb); - /* skb is consumed by slsi_peer_update_assoc_rsp. So do not access this anymore. */ - skb = NULL; - if (peer->assoc_resp_ie) { - reassoc_rsp_ie = peer->assoc_resp_ie->data; - reassoc_rsp_ie_len = peer->assoc_resp_ie->len; - WARN_ON(reassoc_rsp_ie_len && !reassoc_rsp_ie); - } - - /* update the uapsd bitmask according to the bit values - * in wmm information element of association request - */ - if (!sta_wmm_update_uapsd(sdev, dev, peer, assoc_ie, assoc_ie_len)) - SLSI_NET_DBG1(dev, SLSI_MLME, "Fail to update WMM uapsd\n"); - - /* update the acm bitmask according to the acm bit values that - * are included in wmm ie elements of re-association response - */ - if (!sta_wmm_update_wmm_ac_ies(sdev, dev, peer, reassoc_rsp_ie, reassoc_rsp_ie_len)) - SLSI_NET_DBG1(dev, SLSI_MLME, "Fail to update WMM AC ies\n"); - } - - /* cfg80211_connect_result will take a copy of any ASSOC or (RE)ASSOC RSP IEs passed to it */ - cfg80211_connect_result(dev, - peer->address, - assoc_ie, assoc_ie_len, - reassoc_rsp_ie, reassoc_rsp_ie_len, - status, - GFP_KERNEL); - - if (status == WLAN_STATUS_SUCCESS) { - ndev_vif->sta.vif_status = SLSI_VIF_STATUS_CONNECTED; - - /* For Open & WEP AP,send reassoc response. - * For secured AP, all this would be done after handshake - */ - if ((peer->capabilities & WLAN_CAPABILITY_PRIVACY) && - (cfg80211_find_ie(WLAN_EID_RSN, assoc_ie, assoc_ie_len) || - cfg80211_find_ie(SLSI_WLAN_EID_WAPI, assoc_ie, assoc_ie_len) || - cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, assoc_ie, assoc_ie_len))) { - /*secured AP*/ - ndev_vif->sta.resp_id = MLME_REASSOCIATE_RES; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DOING_KEY_CONFIG); - peer->connected_state = SLSI_STA_CONN_STATE_DOING_KEY_CONFIG; - } else { - /*Open/WEP AP*/ - slsi_mlme_reassociate_resp(sdev, dev); - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - peer->connected_state = SLSI_STA_CONN_STATE_CONNECTED; - } - } else { - netif_carrier_off(dev); - slsi_mlme_del_vif(sdev, dev); - slsi_vif_deactivated(sdev, dev); - } - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_connect_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; - struct slsi_peer *peer = NULL; - u8 *assoc_ie = NULL; - int assoc_ie_len = 0; - u8 *assoc_rsp_ie = NULL; - int assoc_rsp_ie_len = 0; - u8 bssid[ETH_ALEN]; - u16 fw_result_code; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - fw_result_code = fapi_get_u16(skb, u.mlme_connect_ind.result_code); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connect_ind(vif:%d, result:0x%04x)\n", - fapi_get_vif(skb), fw_result_code); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit_with_lock; - } - - if (WARN(ndev_vif->vif_type != FAPI_VIFTYPE_STATION, "Not a Station VIF\n")) - goto exit_with_lock; - - if (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTING) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not connecting\n"); - goto exit_with_lock; - } - - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (peer) { - SLSI_ETHER_COPY(bssid, peer->address); - } else { - SLSI_NET_ERR(dev, "!!NO peer record for AP\n"); - eth_zero_addr(bssid); - } - sdev->assoc_result_code = fw_result_code; - if (fw_result_code != FAPI_RESULTCODE_SUCCESS) { - if (fw_result_code == FAPI_RESULTCODE_AUTH_NO_ACK) { - SLSI_INFO(sdev, "Connect failed,Result code:AUTH_NO_ACK\n"); - } else if (fw_result_code == FAPI_RESULTCODE_ASSOC_NO_ACK) { - SLSI_INFO(sdev, "Connect failed,Result code:ASSOC_NO_ACK\n"); - } else if (fw_result_code >= 0x8100 && fw_result_code <= 0x81FF) { - fw_result_code = fw_result_code & 0x00FF; - SLSI_INFO(sdev, "Connect failed(Auth failure), Result code:0x%04x\n", fw_result_code); - } else if (fw_result_code >= 0x8200 && fw_result_code <= 0x82FF) { - fw_result_code = fw_result_code & 0x00FF; - SLSI_INFO(sdev, "Connect failed(Assoc Failure), Result code:0x%04x\n", fw_result_code); - if (fapi_get_datalen(skb)) { - int mgmt_hdr_len; - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - - if (ieee80211_is_assoc_resp(mgmt->frame_control)) { - mgmt_hdr_len = (mgmt->u.assoc_resp.variable - (u8 *)mgmt); - } else if (ieee80211_is_reassoc_resp(mgmt->frame_control)) { - mgmt_hdr_len = (mgmt->u.reassoc_resp.variable - (u8 *)mgmt); - } else { - SLSI_NET_DBG1(dev, SLSI_MLME, "Assoc/Reassoc response not found!\n"); - goto exit_with_lock; - } - - assoc_rsp_ie = (char *)mgmt + mgmt_hdr_len; - assoc_rsp_ie_len = fapi_get_datalen(skb) - mgmt_hdr_len; - } - } else { - SLSI_INFO(sdev, "Connect failed,Result code:0x%04x\n", fw_result_code); - } -#ifdef CONFIG_SCSC_LOG_COLLECTION - /* Trigger log collection if fw result code is not success */ - scsc_log_collector_schedule_collection(SCSC_LOG_HOST_WLAN, SCSC_LOG_HOST_WLAN_REASON_CONNECT_ERR); -#endif - status = fw_result_code; -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG - if (ndev_vif->sta.crypto.wpa_versions == 3) { - const u8 *connecting_ssid = NULL; - int r; - struct cfg80211_external_auth_params auth_request; - - if (ndev_vif->sta.sta_bss->ies->len) - connecting_ssid = cfg80211_find_ie(WLAN_EID_SSID, ndev_vif->sta.sta_bss->ies->data, - ndev_vif->sta.sta_bss->ies->len); - - auth_request.action = NL80211_EXTERNAL_AUTH_ABORT; - memcpy(auth_request.bssid, ndev_vif->sta.sta_bss->bssid, ETH_ALEN); - if (connecting_ssid && (connecting_ssid[1] > 0)) { - memcpy(auth_request.ssid.ssid, &connecting_ssid[2], connecting_ssid[1]); - auth_request.ssid.ssid_len = connecting_ssid[1]; - } - auth_request.key_mgmt_suite = ndev_vif->sta.crypto.akm_suites[0]; - r = cfg80211_external_auth_request(dev, &auth_request, GFP_KERNEL); - if (r) - SLSI_NET_DBG1(dev, SLSI_MLME, "cfg80211_external_auth_request Abort failed"); - } -#endif - } else { - SLSI_INFO(sdev, "Received Association Response\n"); - if (!peer || !peer->assoc_ie) { - if (peer) - WARN(!peer->assoc_ie, "proc-started-ind not received before connect-ind"); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - } else { - if (peer->assoc_ie) { - assoc_ie = peer->assoc_ie->data; - assoc_ie_len = peer->assoc_ie->len; - } - - slsi_peer_update_assoc_rsp(sdev, dev, peer, skb); - /* skb is consumed by slsi_peer_update_assoc_rsp. So do not access this anymore. */ - skb = NULL; - - if (peer->assoc_resp_ie) { - assoc_rsp_ie = peer->assoc_resp_ie->data; - assoc_rsp_ie_len = peer->assoc_resp_ie->len; - } - - /* this is the right place to initialize the bitmasks for - * acm bit and tspec establishment - */ - peer->wmm_acm = 0; - peer->tspec_established = 0; - peer->uapsd = 0; - - /* update the uapsd bitmask according to the bit values - * in wmm information element of association request - */ - if (!sta_wmm_update_uapsd(sdev, dev, peer, assoc_ie, assoc_ie_len)) - SLSI_NET_DBG1(dev, SLSI_MLME, "Fail to update WMM uapsd\n"); - - /* update the wmm ac bitmasks according to the bit values that - * are included in wmm ie elements of association response - */ - if (!sta_wmm_update_wmm_ac_ies(sdev, dev, peer, assoc_rsp_ie, assoc_rsp_ie_len)) - SLSI_NET_DBG1(dev, SLSI_MLME, "Fail to update WMM AC ies\n"); - - WARN_ON(!assoc_rsp_ie_len && !assoc_rsp_ie); - } - - WARN(!ndev_vif->sta.mlme_scan_ind_skb, "mlme_scan.ind not received before connect-ind"); - - if (ndev_vif->sta.mlme_scan_ind_skb) { - SLSI_NET_DBG1(dev, SLSI_MLME, "Sending scan indication to cfg80211, bssid: %pM\n", fapi_get_mgmt(ndev_vif->sta.mlme_scan_ind_skb)->bssid); - - /* saved skb [mlme_scan_ind] freed inside slsi_rx_scan_pass_to_cfg80211 */ - slsi_rx_scan_pass_to_cfg80211(sdev, dev, ndev_vif->sta.mlme_scan_ind_skb); - ndev_vif->sta.mlme_scan_ind_skb = NULL; - } - - if (!ndev_vif->sta.sta_bss) { - if (peer) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - ndev_vif->sta.sta_bss = cfg80211_get_bss(sdev->wiphy, ndev_vif->chan, peer->address, - NULL, 0, IEEE80211_BSS_TYPE_ANY, - IEEE80211_PRIVACY_ANY); -#else - ndev_vif->sta.sta_bss = cfg80211_get_bss(sdev->wiphy, ndev_vif->chan, peer->address, - NULL, 0, 0, 0); -#endif - if (!ndev_vif->sta.sta_bss) { - SLSI_NET_ERR(dev, "sta_bss is not available, terminating the connection (peer: %p)\n", peer); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - } - } - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) - cfg80211_ref_bss(sdev->wiphy, ndev_vif->sta.sta_bss); - cfg80211_connect_bss(dev, bssid, ndev_vif->sta.sta_bss, assoc_ie, assoc_ie_len, assoc_rsp_ie, - assoc_rsp_ie_len, status, GFP_KERNEL, NL80211_TIMEOUT_UNSPECIFIED); -#else - /* cfg80211_connect_result will take a copy of any ASSOC or - * ASSOC RSP IEs passed to it - */ - cfg80211_connect_result(dev, - bssid, - assoc_ie, assoc_ie_len, - assoc_rsp_ie, assoc_rsp_ie_len, - status, - GFP_KERNEL); -#endif - if (status == WLAN_STATUS_SUCCESS) { - ndev_vif->sta.vif_status = SLSI_VIF_STATUS_CONNECTED; - - /* For Open & WEP AP,set the power mode (static IP scenario) ,send connect response and install the packet filters . - * For secured AP, all this would be done after handshake - */ - if ((peer->capabilities & WLAN_CAPABILITY_PRIVACY) && - (cfg80211_find_ie(WLAN_EID_RSN, assoc_ie, assoc_ie_len) || - cfg80211_find_ie(SLSI_WLAN_EID_WAPI, assoc_ie, assoc_ie_len) || - cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, assoc_ie, assoc_ie_len))) { - /*secured AP*/ - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DOING_KEY_CONFIG); - ndev_vif->sta.resp_id = MLME_CONNECT_RES; - } else { - /*Open/WEP AP*/ - slsi_mlme_connect_resp(sdev, dev); - slsi_set_packet_filters(sdev, dev); - - if (ndev_vif->ipaddress) - slsi_mlme_powermgt(sdev, dev, ndev_vif->set_power_mode); - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - } - - /* For P2PCLI, set the Connection Timeout (beacon miss) mib to 10 seconds - * This MIB set failure does not cause any fatal isuue. It just varies the - * detection time of GO's absence from 10 sec to FW default. So Do not disconnect - */ - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) - SLSI_P2P_STATE_CHANGE(sdev, P2P_GROUP_FORMED_CLI); - - /*Update the firmware with cached channels*/ -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - if (!sdev->device_config.roam_scan_mode && ndev_vif->vif_type == FAPI_VIFTYPE_STATION && ndev_vif->activated && ndev_vif->iftype != NL80211_IFTYPE_P2P_CLIENT) { -#else - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION && ndev_vif->activated && ndev_vif->iftype != NL80211_IFTYPE_P2P_CLIENT) { -#endif - const u8 *ssid = cfg80211_find_ie(WLAN_EID_SSID, assoc_ie, assoc_ie_len); - u8 channels[SLSI_ROAMING_CHANNELS_MAX]; - u32 channels_count = slsi_roaming_scan_configure_channels(sdev, dev, ssid, channels); - - if (channels_count) - if (slsi_mlme_set_cached_channels(sdev, dev, channels_count, channels) != 0) - SLSI_NET_ERR(dev, "MLME-SET-CACHED-CHANNELS.req failed\n"); - } - } else { - /* Firmware reported connection success, but driver reported failure to cfg80211: - * send mlme-disconnect.req to firmware - */ - if ((fw_result_code == FAPI_RESULTCODE_SUCCESS) && peer) { - slsi_mlme_disconnect(sdev, dev, peer->address, FAPI_REASONCODE_UNSPECIFIED_REASON, true); - slsi_handle_disconnect(sdev, dev, peer->address, FAPI_REASONCODE_UNSPECIFIED_REASON, NULL, 0); - } else { - slsi_handle_disconnect(sdev, dev, NULL, FAPI_REASONCODE_UNSPECIFIED_REASON, NULL, 0); - } - } - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_disconnect_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_disconnect_ind(vif:%d, MAC:%pM)\n", - fapi_get_vif(skb), - fapi_get_buff(skb, u.mlme_disconnect_ind.peer_sta_address)); - -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_schedule_collection(SCSC_LOG_HOST_WLAN, SCSC_LOG_HOST_WLAN_REASON_DISCONNECT_IND); -#else - mx140_log_dump(); -#endif - - SLSI_INFO(sdev, "Received DEAUTH, reason = 0\n"); - slsi_handle_disconnect(sdev, - dev, - fapi_get_buff(skb, u.mlme_disconnect_ind.peer_sta_address), - 0, - NULL, - 0); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_disconnected_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 reason; - u8 *disassoc_rsp_ie = NULL; - int disassoc_rsp_ie_len = 0; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - reason = fapi_get_u16(skb, u.mlme_disconnected_ind.reason_code); - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_disconnected_ind(vif:%d, reason:%d, MAC:%pM)\n", - fapi_get_vif(skb), - fapi_get_u16(skb, u.mlme_disconnected_ind.reason_code), - fapi_get_buff(skb, u.mlme_disconnected_ind.peer_sta_address)); - -#ifdef CONFIG_SCSC_LOG_COLLECTION - scsc_log_collector_schedule_collection(SCSC_LOG_HOST_WLAN, SCSC_LOG_HOST_WLAN_REASON_DISCONNECTED_IND); -#else - mx140_log_dump(); -#endif - if (reason <= 0xFF) { - SLSI_INFO(sdev, "Received DEAUTH, reason = %d\n", reason); - } else if (reason >= 0x8100 && reason <= 0x81FF) { - reason = reason & 0x00FF; - SLSI_INFO(sdev, "Received DEAUTH, reason = %d\n", reason); - } else if (reason >= 0x8200 && reason <= 0x82FF) { - reason = reason & 0x00FF; - SLSI_INFO(sdev, "Received DISASSOC, reason = %d\n", reason); - } else { - SLSI_INFO(sdev, "Received DEAUTH, reason = Local Disconnect <%d>\n", reason); - } - - if (fapi_get_datalen(skb)) { - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - - if (ieee80211_is_deauth(mgmt->frame_control)) { - disassoc_rsp_ie = (char *)&mgmt->u.deauth.reason_code + 2; - disassoc_rsp_ie_len = fapi_get_datalen(skb) - 2; - } else if (ieee80211_is_disassoc(mgmt->frame_control)) { - disassoc_rsp_ie = (char *)&mgmt->u.disassoc.reason_code + 2; - disassoc_rsp_ie_len = fapi_get_datalen(skb) - 2; - } else { - SLSI_NET_DBG1(dev, SLSI_MLME, "Not a disassoc/deauth packet\n"); - } - } - - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) { - if (fapi_get_u16(skb, u.mlme_disconnected_ind.reason_code) == - FAPI_REASONCODE_HOTSPOT_MAX_CLIENT_REACHED) { - SLSI_NET_DBG1(dev, SLSI_MLME, - "Sending max hotspot client reached notification to user space\n"); - cfg80211_conn_failed(dev, fapi_get_buff(skb, u.mlme_disconnected_ind.peer_sta_address), - NL80211_CONN_FAIL_MAX_CLIENTS, GFP_KERNEL); - goto exit; - } - } - - slsi_handle_disconnect(sdev, - dev, - fapi_get_buff(skb, u.mlme_disconnected_ind.peer_sta_address), - fapi_get_u16(skb, u.mlme_disconnected_ind.reason_code), - disassoc_rsp_ie, - disassoc_rsp_ie_len); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); - return; -} - -/* Handle Procedure Started (Type = Device Discovered) indication for P2P */ -static void slsi_rx_p2p_device_discovered_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - int mgmt_len; - - SLSI_UNUSED_PARAMETER(sdev); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Freq = %d\n", ndev_vif->chan->center_freq); - - /* Only Probe Request is expected as of now */ - mgmt_len = fapi_get_mgmtlen(skb); - if (mgmt_len) { - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - - if (ieee80211_is_mgmt(mgmt->frame_control)) { - if (ieee80211_is_probe_req(mgmt->frame_control)) { - SLSI_NET_DBG3(dev, SLSI_CFG80211, "Received Probe Request\n"); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_rx_mgmt(&ndev_vif->wdev, ndev_vif->chan->center_freq, 0, (const u8 *)mgmt, mgmt_len, GFP_ATOMIC); -#else - cfg80211_rx_mgmt(dev, ndev_vif->chan->center_freq, 0, (const u8 *)mgmt, mgmt_len, GFP_ATOMIC); -#endif - } else - SLSI_NET_ERR(dev, "Ignore Indication - Not Probe Request frame\n"); - } else { - SLSI_NET_ERR(dev, "Ignore Indication - Not Management frame\n"); - } - } -} - -void slsi_rx_procedure_started_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = NULL; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_procedure_started_ind(vif:%d, type:%d, aid:%d)\n", - fapi_get_vif(skb), - fapi_get_u16(skb, u.mlme_procedure_started_ind.procedure_type), - fapi_get_u16(skb, u.mlme_procedure_started_ind.association_identifier)); - SLSI_INFO(sdev, "Send Association Request\n"); - - if (!ndev_vif->activated) { - SLSI_NET_DBG1(dev, SLSI_MLME, "VIF not activated\n"); - goto exit_with_lock; - } - - switch (fapi_get_u16(skb, u.mlme_procedure_started_ind.procedure_type)) { - case FAPI_PROCEDURETYPE_CONNECTION_STARTED: - switch (ndev_vif->vif_type) { - case FAPI_VIFTYPE_AP: - { - u16 aid = fapi_get_u16(skb, u.mlme_procedure_started_ind.association_identifier); - - /* Check for MAX client */ - if ((ndev_vif->peer_sta_records + 1) > SLSI_AP_PEER_CONNECTIONS_MAX) { - SLSI_NET_ERR(dev, "MAX Station limit reached. Ignore ind for aid:%d\n", aid); - goto exit_with_lock; - } - - if (aid < SLSI_PEER_INDEX_MIN || aid > SLSI_PEER_INDEX_MAX) { - SLSI_NET_ERR(dev, "Received incorrect aid: %d\n", aid); - goto exit_with_lock; - } - - peer = slsi_peer_add(sdev, dev, (fapi_get_mgmt(skb))->sa, aid); - if (!peer) { - SLSI_NET_ERR(dev, "Peer NOT Created\n"); - goto exit_with_lock; - } - slsi_peer_update_assoc_req(sdev, dev, peer, skb); - /* skb is consumed by slsi_peer_update_assoc_req. So do not access this anymore. */ - skb = NULL; - peer->connected_state = SLSI_STA_CONN_STATE_CONNECTING; - - if ((ndev_vif->iftype == NL80211_IFTYPE_P2P_GO) && - (peer->assoc_ie) && - (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, peer->assoc_ie->data, peer->assoc_ie->len))) { - SLSI_NET_DBG2(dev, SLSI_MLME, "WPS IE is present. Setting peer->is_wps to TRUE\n"); - peer->is_wps = true; - } - - /* Take a wakelock to avoid platform suspend before EAPOL exchanges (to avoid connection delay) */ - slsi_wakelock_timeout(&sdev->wlan_wl_mlme, SLSI_WAKELOCK_TIME_MSEC_EAPOL); - break; - } - case FAPI_VIFTYPE_STATION: - { - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!peer)) { - SLSI_NET_ERR(dev, "Peer NOT FOUND\n"); - goto exit_with_lock; - } - slsi_peer_update_assoc_req(sdev, dev, peer, skb); - /* skb is consumed by slsi_peer_update_assoc_rsp. So do not access this anymore. */ - skb = NULL; - break; - } - default: - SLSI_NET_ERR(dev, "Incorrect vif type for proceduretype_connection_started\n"); - break; - } - break; - case FAPI_PROCEDURETYPE_DEVICE_DISCOVERED: - /* Expected only in P2P Device and P2P GO role */ - if (WARN_ON(!SLSI_IS_VIF_INDEX_P2P(ndev_vif) && (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO))) - goto exit_with_lock; - - /* Send probe request to supplicant only if in listening state. Issues were seen earlier if - * Probe request was sent to supplicant while waiting for GO Neg Req from peer. - * Send Probe request to supplicant if received in GO mode - */ - if ((sdev->p2p_state == P2P_LISTENING) || (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO)) - slsi_rx_p2p_device_discovered_ind(sdev, dev, skb); - break; - case FAPI_PROCEDURETYPE_ROAMING_STARTED: - { - SLSI_NET_DBG1(dev, SLSI_MLME, "Roaming Procedure Starting with %pM\n", (fapi_get_mgmt(skb))->bssid); - if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION)) - goto exit_with_lock; - if (WARN_ON(!ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET] || !ndev_vif->peer_sta_record[SLSI_STA_PEER_QUEUESET]->valid)) - goto exit_with_lock; - slsi_kfree_skb(ndev_vif->sta.roam_mlme_procedure_started_ind); - ndev_vif->sta.roam_mlme_procedure_started_ind = skb; - /* skb is consumed here. So remove reference to this.*/ - skb = NULL; - break; - } - default: - SLSI_NET_DBG1(dev, SLSI_MLME, "Unknown Procedure: %d\n", fapi_get_u16(skb, u.mlme_procedure_started_ind.procedure_type)); - goto exit_with_lock; - } - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_frame_transmission_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - u16 host_tag = fapi_get_u16(skb, u.mlme_frame_transmission_ind.host_tag); - u16 tx_status = fapi_get_u16(skb, u.mlme_frame_transmission_ind.transmission_status); - bool ack = true; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_frame_transmission_ind(vif:%d, host_tag:%d, transmission_status:%d)\n", fapi_get_vif(skb), - host_tag, - tx_status); - - if (ndev_vif->mgmt_tx_data.host_tag == host_tag) { - struct netdev_vif *ndev_vif_to_cfg = ndev_vif; - - /* If frame tx failed allow del_vif work to take care of vif deletion. - * This work would be queued as part of frame_tx with the wait duration - */ - if (tx_status != FAPI_TRANSMISSIONSTATUS_SUCCESSFUL) { - ack = false; - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - if (sdev->wlan_unsync_vif_state == WLAN_UNSYNC_VIF_TX) - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_VIF_ACTIVE; /*We wouldn't delete VIF*/ - } else { - if (sdev->p2p_group_exp_frame != SLSI_P2P_PA_INVALID) - slsi_clear_offchannel_data(sdev, false); - else if (ndev_vif->mgmt_tx_data.exp_frame != SLSI_P2P_PA_INVALID) - (void)slsi_mlme_reset_dwell_time(sdev, dev); - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - } - } - - /* Change state if frame tx was in Listen as peer response is not expected */ - if (SLSI_IS_VIF_INDEX_P2P(ndev_vif) && (ndev_vif->mgmt_tx_data.exp_frame == SLSI_P2P_PA_INVALID)) { - if (delayed_work_pending(&ndev_vif->unsync.roc_expiry_work)) - SLSI_P2P_STATE_CHANGE(sdev, P2P_LISTENING); - else - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE); - } else if (SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif)) { - const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *)ndev_vif->mgmt_tx_data.buf; - - /* If frame transmission was initiated on P2P device vif by supplicant, then use the net_dev of that vif (i.e. p2p0) */ - if ((mgmt) && (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)) { - struct net_device *ndev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2P); - - SLSI_NET_DBG2(dev, SLSI_MLME, "Frame Tx was requested with device address - Change ndev_vif for tx_status\n"); - - ndev_vif_to_cfg = netdev_priv(ndev); - if (!ndev_vif_to_cfg) { - SLSI_NET_ERR(dev, "Getting P2P Index netdev failed\n"); - ndev_vif_to_cfg = ndev_vif; - } - } - } -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - if (!sdev->device_config.wes_mode) { -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) - cfg80211_mgmt_tx_status(&ndev_vif_to_cfg->wdev, ndev_vif->mgmt_tx_data.cookie, ndev_vif->mgmt_tx_data.buf, ndev_vif->mgmt_tx_data.buf_len, ack, GFP_KERNEL); -#else - cfg80211_mgmt_tx_status(ndev_vif_to_cfg->wdev.netdev, ndev_vif->mgmt_tx_data.cookie, ndev_vif->mgmt_tx_data.buf, ndev_vif->mgmt_tx_data.buf_len, ack, GFP_KERNEL); -#endif - -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - } -#endif - (void)slsi_set_mgmt_tx_data(ndev_vif, 0, 0, NULL, 0); - } - - if ((tx_status == FAPI_TRANSMISSIONSTATUS_SUCCESSFUL) || (tx_status == FAPI_TRANSMISSIONSTATUS_RETRY_LIMIT)) { -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - if (ndev_vif->enhanced_arp_detect_enabled && (ndev_vif->vif_type == FAPI_VIFTYPE_STATION)) { - int i = 0; - - for (i = 0; i < SLSI_MAX_ARP_SEND_FRAME; i++) { - if (ndev_vif->enhanced_arp_host_tag[i] == host_tag) { - ndev_vif->enhanced_arp_host_tag[i] = 0; - ndev_vif->enhanced_arp_stats.arp_req_rx_count_by_lower_mac++; - if (tx_status == FAPI_TRANSMISSIONSTATUS_SUCCESSFUL) - ndev_vif->enhanced_arp_stats.arp_req_count_tx_success++; - break; - } - } - } -#endif - if ((ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_vif->sta.m4_host_tag == host_tag)) { - switch (ndev_vif->sta.resp_id) { - case MLME_ROAMED_RES: - slsi_mlme_roamed_resp(sdev, dev); - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!peer)) - break; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - cac_update_roam_traffic_params(sdev, dev); - break; - case MLME_CONNECT_RES: - slsi_mlme_connect_resp(sdev, dev); - slsi_set_packet_filters(sdev, dev); - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (WARN_ON(!peer)) - break; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - break; - case MLME_REASSOCIATE_RES: - slsi_mlme_reassociate_resp(sdev, dev); - break; - default: - break; - } - ndev_vif->sta.m4_host_tag = 0; - ndev_vif->sta.resp_id = 0; - } - if (tx_status == FAPI_TRANSMISSIONSTATUS_RETRY_LIMIT) { - if ((ndev_vif->iftype == NL80211_IFTYPE_STATION) && - (ndev_vif->sta.eap_hosttag == host_tag)) { - if (ndev_vif->sta.sta_bss) { - SLSI_NET_WARN(dev, "Disconnect as EAP frame transmission failed\n"); - slsi_mlme_disconnect(sdev, dev, ndev_vif->sta.sta_bss->bssid, FAPI_REASONCODE_UNSPECIFIED_REASON, false); - } else { - SLSI_NET_WARN(dev, "EAP frame transmission failed, sta_bss not available\n"); - } - } - ndev_vif->stats.tx_errors++; - } - } else { - ndev_vif->stats.tx_errors++; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_received_frame_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 data_unit_descriptor = fapi_get_u16(skb, u.mlme_received_frame_ind.data_unit_descriptor); - u16 frequency = SLSI_FREQ_FW_TO_HOST(fapi_get_u16(skb, u.mlme_received_frame_ind.channel_frequency)); - u8 *eapol = NULL; - u8 *eap = NULL; - u16 protocol = 0; - u32 dhcp_message_type = SLSI_DHCP_MESSAGE_TYPE_INVALID; - u16 eap_length = 0; - - SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_received_frame_ind(vif:%d, data descriptor:%d, freq:%d)\n", - fapi_get_vif(skb), - data_unit_descriptor, - frequency); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (data_unit_descriptor == FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME) { - struct ieee80211_mgmt *mgmt; - int mgmt_len; - - mgmt_len = fapi_get_mgmtlen(skb); - if (!mgmt_len) - goto exit; - mgmt = fapi_get_mgmt(skb); - if (ieee80211_is_auth(mgmt->frame_control)) { - cfg80211_rx_mgmt(&ndev_vif->wdev, frequency, 0, (const u8 *)mgmt, mgmt_len, GFP_ATOMIC); - goto exit; - } -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - if (ndev_vif->is_wips_running && ieee80211_is_beacon(mgmt->frame_control) && - SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { - slsi_handle_wips_beacon(sdev, dev, skb, mgmt, mgmt_len); - goto exit; - } -#endif - if (WARN_ON(!(ieee80211_is_action(mgmt->frame_control)))) - goto exit; - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - if (slsi_is_wes_action_frame(mgmt)) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Received NCHO WES VS action frame\n"); - if (!sdev->device_config.wes_mode) - goto exit; - } else { -#endif - if (mgmt->u.action.category == WLAN_CATEGORY_WMM) { - cac_rx_wmm_action(sdev, dev, mgmt, mgmt_len); - } else { - slsi_wlan_dump_public_action_subtype(sdev, mgmt, false); - if (sdev->wlan_unsync_vif_state == WLAN_UNSYNC_VIF_TX) - sdev->wlan_unsync_vif_state = WLAN_UNSYNC_VIF_ACTIVE; - } -#ifdef CONFIG_SCSC_WLAN_WES_NCHO - } -#endif - } else { - int subtype = slsi_p2p_get_public_action_subtype(mgmt); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Received action frame (%s)\n", slsi_p2p_pa_subtype_text(subtype)); - - if (SLSI_IS_P2P_UNSYNC_VIF(ndev_vif) && (ndev_vif->mgmt_tx_data.exp_frame != SLSI_P2P_PA_INVALID) && (subtype == ndev_vif->mgmt_tx_data.exp_frame)) { - if (sdev->p2p_state == P2P_LISTENING) - SLSI_NET_WARN(dev, "Driver in incorrect P2P state (P2P_LISTENING)"); - - cancel_delayed_work(&ndev_vif->unsync.del_vif_work); - /* Sending down the Unset channel is delayed when listen work expires in - * middle of P2P procedure. For example,When Listen Work expires after - * sending provision discovery req,unset channel is not sent to FW. - * After Receiving the PROV_DISC_RESP, if listen work is not present - * Unset channel to be sent down.Similarly During P2P Negotiation procedure, - * Unset channel is not sent to FW.Once Negotiation is complete, - * if listen work is not present Unset channel to be sent down. - */ - if ((subtype == SLSI_P2P_PA_GO_NEG_CFM) || (subtype == SLSI_P2P_PA_PROV_DISC_RSP)) { - ndev_vif->drv_in_p2p_procedure = false; - if (!delayed_work_pending(&ndev_vif->unsync.roc_expiry_work)) { - slsi_mlme_unset_channel_req(ndev_vif->sdev, ndev_vif->wdev.netdev); - ndev_vif->driver_channel = 0; - } - } - - ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID; - (void)slsi_mlme_reset_dwell_time(sdev, dev); - if (delayed_work_pending(&ndev_vif->unsync.roc_expiry_work)) { - SLSI_P2P_STATE_CHANGE(sdev, P2P_LISTENING); - } else { - queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.del_vif_work, - msecs_to_jiffies(SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC)); - SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE); - } - } else if ((sdev->p2p_group_exp_frame != SLSI_P2P_PA_INVALID) && (sdev->p2p_group_exp_frame == subtype)) { - SLSI_NET_DBG2(dev, SLSI_MLME, "Expected action frame (%s) received on Group VIF\n", slsi_p2p_pa_subtype_text(subtype)); - slsi_clear_offchannel_data(sdev, - (!SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, - ndev_vif)) ? true : false); - } - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_rx_mgmt(&ndev_vif->wdev, frequency, 0, (const u8 *)mgmt, mgmt_len, GFP_ATOMIC); -#else - cfg80211_rx_mgmt(dev, frequency, 0, (const u8 *)mgmt, mgmt_len, GFP_ATOMIC); -#endif - } else if (data_unit_descriptor == FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME) { - struct slsi_peer *peer = NULL; - struct ethhdr *ehdr = (struct ethhdr *)fapi_get_data(skb); - - peer = slsi_get_peer_from_mac(sdev, dev, ehdr->h_source); - if (!peer) { - SLSI_DBG1(sdev, SLSI_RX, "drop packet as No peer found\n"); - goto exit; - } - - /* strip signal and any signal/bulk roundings/offsets */ - skb_pull(skb, fapi_get_siglen(skb)); - - skb->dev = dev; - skb->ip_summed = CHECKSUM_NONE; - - ndev_vif->stats.rx_packets++; - ndev_vif->stats.rx_bytes += skb->len; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 10, 0)) - dev->last_rx = jiffies; -#endif - /* Storing Data for Logging Information */ - if ((skb->len - sizeof(struct ethhdr)) >= 99) - eapol = skb->data + sizeof(struct ethhdr); - - if ((skb->len - sizeof(struct ethhdr)) >= 9) { - eap_length = (skb->len - sizeof(struct ethhdr)) - 4; - eap = skb->data + sizeof(struct ethhdr); - } - if (skb->len >= 285 && slsi_is_dhcp_packet(skb->data) != SLSI_TX_IS_NOT_DHCP) - dhcp_message_type = skb->data[284]; - - skb->protocol = eth_type_trans(skb, dev); - protocol = ntohs(skb->protocol); - if (protocol == ETH_P_PAE) { - if (eapol && eapol[SLSI_EAPOL_IEEE8021X_TYPE_POS] == SLSI_IEEE8021X_TYPE_EAPOL_KEY) { - if ((eapol[SLSI_EAPOL_TYPE_POS] == SLSI_EAPOL_TYPE_RSN_KEY || - eapol[SLSI_EAPOL_TYPE_POS] == SLSI_EAPOL_TYPE_WPA_KEY) && - (eapol[SLSI_EAPOL_KEY_INFO_LOWER_BYTE_POS] & - SLSI_EAPOL_KEY_INFO_KEY_TYPE_BIT_IN_LOWER_BYTE) && - (eapol[SLSI_EAPOL_KEY_INFO_HIGHER_BYTE_POS] & - SLSI_EAPOL_KEY_INFO_MIC_BIT_IN_HIGHER_BYTE) && - (eapol[SLSI_EAPOL_KEY_DATA_LENGTH_HIGHER_BYTE_POS] == 0) && - (eapol[SLSI_EAPOL_KEY_DATA_LENGTH_LOWER_BYTE_POS] == 0)) { - SLSI_INFO(sdev, "Received 4way-H/S, M4\n"); - } else if (!(eapol[SLSI_EAPOL_KEY_INFO_HIGHER_BYTE_POS] & - SLSI_EAPOL_KEY_INFO_MIC_BIT_IN_HIGHER_BYTE)) { - SLSI_INFO(sdev, "Received 4way-H/S, M1\n"); - } else if (eapol[SLSI_EAPOL_KEY_INFO_HIGHER_BYTE_POS] & - SLSI_EAPOL_KEY_INFO_SECURE_BIT_IN_HIGHER_BYTE) { - SLSI_INFO(sdev, "Received 4way-H/S, M3\n"); - } else { - SLSI_INFO(sdev, "Received 4way-H/S, M2\n"); - } - } else if (eap && eap[SLSI_EAPOL_IEEE8021X_TYPE_POS] == SLSI_IEEE8021X_TYPE_EAP_PACKET) { - if (eap[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_REQUEST) - SLSI_INFO(sdev, "Received EAP-Request (%d)\n", eap_length); - else if (eap[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_RESPONSE) - SLSI_INFO(sdev, "Received EAP-Response (%d)\n", eap_length); - else if (eap[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_SUCCESS) - SLSI_INFO(sdev, "Received EAP-Success (%d)\n", eap_length); - else if (eap[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_FAILURE) - SLSI_INFO(sdev, "Received EAP-Failure (%d)\n", eap_length); - } - } else if (protocol == ETH_P_IP) { - if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_DISCOVER) - SLSI_INFO(sdev, "Received DHCP [DISCOVER]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_OFFER) - SLSI_INFO(sdev, "Received DHCP [OFFER]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_REQUEST) - SLSI_INFO(sdev, "Received DHCP [REQUEST]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_DECLINE) - SLSI_INFO(sdev, "Received DHCP [DECLINE]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_ACK) - SLSI_INFO(sdev, "Received DHCP [ACK]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_NAK) - SLSI_INFO(sdev, "Received DHCP [NAK]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_RELEASE) - SLSI_INFO(sdev, "Received DHCP [RELEASE]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_INFORM) - SLSI_INFO(sdev, "Received DHCP [INFORM]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_FORCERENEW) - SLSI_INFO(sdev, "Received DHCP [FORCERENEW]\n"); - else - SLSI_INFO(sdev, "Received DHCP [INVALID]\n"); - } - slsi_dbg_untrack_skb(skb); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - SLSI_DBG2(sdev, SLSI_MLME, "pass %u bytes up (proto:%d)\n", skb->len, ntohs(skb->protocol)); - netif_rx_ni(skb); - slsi_wakelock_timeout(&sdev->wlan_wl_mlme, SLSI_WAKELOCK_TIME_MSEC_EAPOL); - return; - } -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_mic_failure_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u8 *mac_addr; - u16 key_type, key_id; - enum nl80211_key_type nl_key_type; - - SLSI_UNUSED_PARAMETER(sdev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - mac_addr = fapi_get_buff(skb, u.mlme_disconnected_ind.peer_sta_address); - key_type = fapi_get_u16(skb, u.mlme_mic_failure_ind.key_type); - key_id = fapi_get_u16(skb, u.mlme_mic_failure_ind.key_id); - - SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_mic_failure_ind(vif:%d, MAC:%pM, key_type:%d, key_id:%d)\n", - fapi_get_vif(skb), mac_addr, key_type, key_id); - - if (WARN_ON((key_type != FAPI_KEYTYPE_GROUP) && (key_type != FAPI_KEYTYPE_PAIRWISE))) - goto exit; - - nl_key_type = (key_type == FAPI_KEYTYPE_GROUP) ? NL80211_KEYTYPE_GROUP : NL80211_KEYTYPE_PAIRWISE; - - cfg80211_michael_mic_failure(dev, mac_addr, nl_key_type, key_id, NULL, GFP_KERNEL); - -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -/** - * Handler for mlme_listen_end_ind. - * The listen_end_ind would be received when the total Listen Offloading time is over. - * Indicate completion of Listen Offloading to supplicant by sending Cancel-ROC event - * with cookie 0xffff. Queue delayed work for unsync vif deletion. - */ -void slsi_rx_listen_end_ind(struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Inform completion of P2P Listen Offloading\n"); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - cfg80211_remain_on_channel_expired(&ndev_vif->wdev, 0xffff, ndev_vif->chan, GFP_KERNEL); -#else - cfg80211_remain_on_channel_expired(ndev_vif->wdev.netdev, 0xffff, ndev_vif->chan, ndev_vif->channel_type, GFP_KERNEL); -#endif - - ndev_vif->unsync.listen_offload = false; - - slsi_p2p_queue_unsync_vif_del_work(ndev_vif, SLSI_P2P_UNSYNC_VIF_EXTRA_MSEC); - - SLSI_P2P_STATE_CHANGE(ndev_vif->sdev, P2P_IDLE_VIF_ACTIVE); - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - slsi_kfree_skb(skb); -} - -static int slsi_rx_wait_ind_match(u16 recv_id, u16 wait_id) -{ - if (recv_id == wait_id) - return 1; - if (wait_id == MLME_DISCONNECT_IND && recv_id == MLME_DISCONNECTED_IND) - return 1; - return 0; -} - -int slsi_rx_blocking_signals(struct slsi_dev *sdev, struct sk_buff *skb) -{ - u16 pid, id; - struct slsi_sig_send *sig_wait; - u16 vif = fapi_get_vif(skb); - - sig_wait = &sdev->sig_wait; - id = fapi_get_sigid(skb); - pid = fapi_get_u16(skb, receiver_pid); - - /* ALL mlme cfm signals MUST have blocking call waiting for it (Per Vif or Global) */ - if (fapi_is_cfm(skb)) { - struct net_device *dev; - struct netdev_vif *ndev_vif; - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (dev) { - ndev_vif = netdev_priv(dev); - sig_wait = &ndev_vif->sig_wait; - } - spin_lock_bh(&sig_wait->send_signal_lock); - if (id == sig_wait->cfm_id && pid == sig_wait->process_id) { - if (WARN_ON(sig_wait->cfm)) - slsi_kfree_skb(sig_wait->cfm); - sig_wait->cfm = skb; - spin_unlock_bh(&sig_wait->send_signal_lock); - complete(&sig_wait->completion); - rcu_read_unlock(); - return 0; - } - /** - * Important data frames such as EAPOL, ARP, DHCP are send - * over MLME. For these frames driver does not block on confirms. - * So there can be unexpected confirms here for such data frames. - * These confirms are treated as normal and is silently dropped - * here - */ - if (id == MLME_SEND_FRAME_CFM) { - spin_unlock_bh(&sig_wait->send_signal_lock); - rcu_read_unlock(); - slsi_kfree_skb(skb); - return 0; - } - - SLSI_DBG1(sdev, SLSI_MLME, "Unexpected cfm(0x%.4x, pid:0x%.4x, vif:%d)\n", id, pid, vif); - spin_unlock_bh(&sig_wait->send_signal_lock); - rcu_read_unlock(); - return -EINVAL; - } - /* Some mlme ind signals have a blocking call waiting (Per Vif or Global) */ - if (fapi_is_ind(skb)) { - struct net_device *dev; - struct netdev_vif *ndev_vif; - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (dev) { - ndev_vif = netdev_priv(dev); - sig_wait = &ndev_vif->sig_wait; - } - spin_lock_bh(&sig_wait->send_signal_lock); - if (slsi_rx_wait_ind_match(id, sig_wait->ind_id) && pid == sig_wait->process_id) { - if (WARN_ON(sig_wait->ind)) - slsi_kfree_skb(sig_wait->ind); - sig_wait->ind = skb; - spin_unlock_bh(&sig_wait->send_signal_lock); - complete(&sig_wait->completion); - rcu_read_unlock(); - return 0; - } - spin_unlock_bh(&sig_wait->send_signal_lock); - rcu_read_unlock(); - } - return -EINVAL; -} diff --git a/drivers/net/wireless/scsc/sap.h b/drivers/net/wireless/scsc/sap.h deleted file mode 100644 index 3c7c1e36ff52..000000000000 --- a/drivers/net/wireless/scsc/sap.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SAP_H__ -#define __SAP_H__ - -/* Number of SAPs */ -#define SAP_TOTAL 4 - -#define SAP_MLME 0 -#define SAP_MA 1 -#define SAP_DBG 2 -#define SAP_TST 3 - -/* Max number of versions supported */ -#define SAP_MAX_VER 2 - -#define SAP_MAJOR(version) ((version & 0xff00) >> 8) -#define SAP_MINOR(version) (version & 0xff) - -struct slsi_dev; -struct sk_buff; - -struct sap_api { - u8 sap_class; - u16 sap_versions[SAP_MAX_VER]; - int (*sap_version_supported)(u16 version); - int (*sap_handler)(struct slsi_dev *sdev, struct sk_buff *skb); - int (*sap_txdone)(struct slsi_dev *sdev, u16 colour); - int (*sap_notifier)(struct slsi_dev *sdev, unsigned long event); -}; -#endif diff --git a/drivers/net/wireless/scsc/sap_dbg.c b/drivers/net/wireless/scsc/sap_dbg.c deleted file mode 100644 index 6ca436b33cf7..000000000000 --- a/drivers/net/wireless/scsc/sap_dbg.c +++ /dev/null @@ -1,173 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include "debug.h" -#include "dev.h" -#include "sap.h" -#include "sap_dbg.h" -#include "hip.h" - -#define SUPPORTED_OLD_VERSION 0 - -static int sap_dbg_version_supported(u16 version); -static int sap_dbg_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb); - -static struct sap_api sap_dbg = { - .sap_class = SAP_DBG, - .sap_version_supported = sap_dbg_version_supported, - .sap_handler = sap_dbg_rx_handler, - .sap_versions = { FAPI_DEBUG_SAP_VERSION, SUPPORTED_OLD_VERSION }, -}; - -static int sap_dbg_version_supported(u16 version) -{ - unsigned int major = SAP_MAJOR(version); - unsigned int minor = SAP_MINOR(version); - u8 i = 0; - - SLSI_INFO_NODEV("Reported version: %d.%d\n", major, minor); - - for (i = 0; i < SAP_MAX_VER; i++) - if (SAP_MAJOR(sap_dbg.sap_versions[i]) == major) - return 0; - - SLSI_ERR_NODEV("Version %d.%d Not supported\n", major, minor); - - return -EINVAL; -} - -static void slsi_rx_debug(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 id = fapi_get_u16(skb, id); - - SLSI_UNUSED_PARAMETER(dev); - - switch (id) { - case DEBUG_FAULT_IND: - SLSI_WARN(sdev, "WF_FW_INFO: |cpu %s|id 0x%04X|arg 0x%08X|count %d|timestamp %10u|\n", - ((fapi_get_u16(skb, u.debug_fault_ind.cpu) == 0x8000) ? "MAC" : - (fapi_get_u16(skb, u.debug_fault_ind.cpu) == 0x4000) ? "PHY" : "???"), - fapi_get_u16(skb, u.debug_fault_ind.faultid), - fapi_get_u32(skb, u.debug_fault_ind.arg), - fapi_get_u16(skb, u.debug_fault_ind.count), - fapi_get_u32(skb, u.debug_fault_ind.timestamp)); - break; - case DEBUG_WORD12IND: - atomic_inc(&sdev->debug_inds); - SLSI_DBG4(sdev, SLSI_FW_TEST, "FW DEBUG(id:%d, subid:%d, vif:%d, time:%u) %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X\n", - fapi_get_u16(skb, u.debug_word12_ind.module_id), - fapi_get_u16(skb, u.debug_word12_ind.module_sub_id), - fapi_get_vif(skb), - fapi_get_u32(skb, u.debug_word12_ind.timestamp), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[0]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[1]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[2]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[3]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[4]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[5]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[6]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[7]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[8]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[9]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[10]), - fapi_get_u16(skb, u.debug_word12_ind.debug_words[11])); - break; - default: - SLSI_DBG1(sdev, SLSI_MLME, "Unhandled Debug Ind: 0x%.4x\n", id); - break; - } - slsi_kfree_skb(skb); -} - -static int slsi_rx_dbg_sap(struct slsi_dev *sdev, struct sk_buff *skb) -{ - u16 id = fapi_get_u16(skb, id); - u16 vif = fapi_get_vif(skb); - struct net_device *dev; - - switch (id) { - case DEBUG_FAULT_IND: - case DEBUG_WORD12IND: - case DEBUG_GENERIC_IND: - slsi_rx_debug(sdev, NULL, skb); - break; - case DEBUG_PKT_SINK_REPORT_IND: - { - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (!dev) { - rcu_read_unlock(); - slsi_kfree_skb(skb); - break; - } - slsi_rx_sink_report(sdev, dev, skb); - rcu_read_unlock(); - break; - } - case DEBUG_PKT_GEN_REPORT_IND: - { - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (!dev) { - rcu_read_unlock(); - slsi_kfree_skb(skb); - break; - } - slsi_rx_gen_report(sdev, dev, skb); - rcu_read_unlock(); - break; - } - default: - slsi_kfree_skb(skb); - SLSI_ERR(sdev, "Unhandled Ind: 0x%.4x\n", id); - break; - } - - return 0; -} - -void slsi_rx_dbg_sap_work(struct work_struct *work) -{ - struct slsi_skb_work *w = container_of(work, struct slsi_skb_work, work); - struct slsi_dev *sdev = w->sdev; - struct sk_buff *skb = slsi_skb_work_dequeue(w); - - slsi_wakelock(&sdev->wlan_wl); - while (skb) { - slsi_debug_frame(sdev, NULL, skb, "RX"); - slsi_rx_dbg_sap(sdev, skb); - skb = slsi_skb_work_dequeue(w); - } - slsi_wakeunlock(&sdev->wlan_wl); -} - -static int sap_dbg_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb) -{ - /* DEBUG SAP has a generic confirm. Theoretically, that - * can mean upper layer code can block on the confirm. - */ - if (slsi_rx_blocking_signals(sdev, skb) == 0) - return 0; - - slsi_skb_work_enqueue(&sdev->rx_dbg_sap, skb); - return 0; -} - -int sap_dbg_init(void) -{ - SLSI_INFO_NODEV("Registering SAP\n"); - - slsi_hip_sap_register(&sap_dbg); - - return 0; -} - -int sap_dbg_deinit(void) -{ - SLSI_INFO_NODEV("Unregistering SAP\n"); - slsi_hip_sap_unregister(&sap_dbg); - return 0; -} diff --git a/drivers/net/wireless/scsc/sap_dbg.h b/drivers/net/wireless/scsc/sap_dbg.h deleted file mode 100644 index fb52f79dbd28..000000000000 --- a/drivers/net/wireless/scsc/sap_dbg.h +++ /dev/null @@ -1,14 +0,0 @@ - -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SAP_DBG_H__ -#define __SAP_DBG_H__ - -int sap_dbg_init(void); -int sap_dbg_deinit(void); - -#endif diff --git a/drivers/net/wireless/scsc/sap_ma.c b/drivers/net/wireless/scsc/sap_ma.c deleted file mode 100755 index c3fc8a3ae6e2..000000000000 --- a/drivers/net/wireless/scsc/sap_ma.c +++ /dev/null @@ -1,752 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include "debug.h" -#include "dev.h" -#include "sap.h" -#include "sap_ma.h" -#include "hip.h" -#include "ba.h" -#include "mgt.h" -#include "nl80211_vendor.h" -#include "hip4_sampler.h" -#include "traffic_monitor.h" - -#ifdef CONFIG_ANDROID -#include "scsc_wifilogger_rings.h" -#endif - -#define SUPPORTED_OLD_VERSION 0 - -static int sap_ma_version_supported(u16 version); -static int sap_ma_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb); -static int sap_ma_txdone(struct slsi_dev *sdev, u16 colour); -static int sap_ma_notifier(struct slsi_dev *sdev, unsigned long event); - -static struct sap_api sap_ma = { - .sap_class = SAP_MA, - .sap_version_supported = sap_ma_version_supported, - .sap_handler = sap_ma_rx_handler, - .sap_versions = { FAPI_DATA_SAP_VERSION, SUPPORTED_OLD_VERSION }, - .sap_txdone = sap_ma_txdone, - .sap_notifier = sap_ma_notifier, -}; - -static int sap_ma_notifier(struct slsi_dev *sdev, unsigned long event) -{ - uint vif; - - SLSI_INFO_NODEV("Notifier event received: %lu\n", event); - if (event >= SCSC_MAX_NOTIFIER) - return -EIO; - - switch (event) { - case SCSC_WIFI_STOP: - SLSI_INFO_NODEV("Stop netdev queues\n"); - rcu_read_lock(); - for (vif = SLSI_NET_INDEX_WLAN; - vif <= SLSI_NET_INDEX_P2PX_SWLAN; vif++) { - struct net_device *ndev = - slsi_get_netdev_rcu(sdev, vif); - if (ndev && !netif_queue_stopped(ndev)) - netif_tx_stop_all_queues(ndev); - } - rcu_read_unlock(); - break; - - case SCSC_WIFI_FAILURE_RESET: - SLSI_DBG1_NODEV(SLSI_NETDEV, "Netdevs queues will not be restarted - recovery will take care of it\n"); - break; - - case SCSC_WIFI_SUSPEND: - break; - - case SCSC_WIFI_RESUME: - break; - default: - SLSI_INFO_NODEV("Unknown event code %lu\n", event); - break; - } - - return 0; -} - -static int sap_ma_version_supported(u16 version) -{ - unsigned int major = SAP_MAJOR(version); - unsigned int minor = SAP_MINOR(version); - u8 i = 0; - - SLSI_INFO_NODEV("Reported version: %d.%d\n", major, minor); - - for (i = 0; i < SAP_MAX_VER; i++) - if (SAP_MAJOR(sap_ma.sap_versions[i]) == major) - return 0; - - SLSI_ERR_NODEV("Version %d.%d Not supported\n", major, minor); - - return -EINVAL; -} - -static int slsi_rx_amsdu_deaggregate(struct net_device *dev, struct sk_buff *skb, struct sk_buff_head *msdu_list) -{ - unsigned int msdu_len; - unsigned int subframe_len; - int padding; - struct sk_buff *subframe = NULL; - bool last_sub_frame = false; - const unsigned char mac_0[ETH_ALEN] = { 0 }; - bool skip_frame = false; - struct ethhdr *mh; - - SLSI_NET_DBG4(dev, SLSI_RX, "A-MSDU received (len:%d)\n", skb->len); - - while (!last_sub_frame) { - msdu_len = (skb->data[ETH_ALEN * 2] << 8) | skb->data[(ETH_ALEN * 2) + 1]; - - /* check if the length of sub-frame is valid */ - if (msdu_len > skb->len) { - SLSI_NET_ERR(dev, "invalid MSDU length %d, SKB length = %d\n", msdu_len, skb->len); - slsi_kfree_skb(skb); - return -EINVAL; - } - - subframe_len = msdu_len + (2 * ETH_ALEN) + 2; - - /* For the last subframe skb length and subframe length will be same */ - if (skb->len == subframe_len) { - subframe = slsi_skb_copy(skb, GFP_ATOMIC); - - if (!subframe) { - SLSI_NET_ERR(dev, "failed to alloc the SKB for A-MSDU subframe\n"); - __skb_queue_purge(msdu_list); - slsi_kfree_skb(skb); - return -ENOMEM; - } - - /* There is no padding for last subframe */ - padding = 0; - last_sub_frame = true; - } else { - /* Copy the skb for the subframe */ - subframe = slsi_skb_copy(skb, GFP_ATOMIC); - - if (!subframe) { - SLSI_NET_ERR(dev, "failed to alloc the SKB for A-MSDU subframe\n"); - __skb_queue_purge(msdu_list); - slsi_kfree_skb(skb); - return -ENOMEM; - } - - padding = (4 - (subframe_len % 4)) & 0x3; - } - - /* Remove the other subframes by adjusting the tail pointer of the copied skb */ - skb_trim(subframe, subframe_len); - - /* Overwrite LLC+SNAP header with src and dest addr */ - SLSI_ETHER_COPY(&subframe->data[14], &subframe->data[6]); - SLSI_ETHER_COPY(&subframe->data[8], &subframe->data[0]); - - /* Remove 8 bytes of LLC+SNAP header */ - skb_pull(subframe, LLC_SNAP_HDR_LEN); - - SLSI_NET_DBG_HEX(dev, SLSI_RX, subframe->data, - subframe->len < 64 ? subframe->len : 64, "Subframe before giving to OS:\n"); - - /* Before preparing the skb, filter out if the Destination Address of the Ethernet frame - * or A-MSDU subframe is set to an invalid value, i.e. all zeros - */ - skb_set_mac_header(subframe, 0); - mh = eth_hdr(subframe); - if (SLSI_ETHER_EQUAL(mh->h_dest, mac_0)) { - SLSI_NET_DBG3(dev, SLSI_RX, "msdu subframe filtered out: MAC destination address %pM\n", mh->h_dest); - skip_frame = true; - } - - /* If this is not the last subframe then move to the next subframe */ - if (!last_sub_frame) - skb_pull(skb, (subframe_len + padding)); - - /* If this frame has been filtered out, free the clone and continue */ - if (skip_frame) { - skip_frame = false; - /* Free the the skbuff structure itself but not the data */ - /* skb will be freed if it is the last subframe (i.e. subframe == skb) */ - slsi_kfree_skb(subframe); - continue; - } - __skb_queue_tail(msdu_list, subframe); - } - slsi_kfree_skb(skb); - return 0; -} - -static inline bool slsi_rx_is_amsdu(struct sk_buff *skb) -{ - return (fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor) == FAPI_DATAUNITDESCRIPTOR_AMSDU); -} - -void slsi_rx_data_deliver_skb(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, bool from_ba_timer) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff_head msdu_list; - struct slsi_peer *peer = NULL; - struct ethhdr *eth_hdr; - bool is_amsdu = slsi_rx_is_amsdu(skb); - u8 trafic_q = slsi_frame_priority_to_ac_queue(fapi_get_u16(skb, u.ma_unitdata_ind.priority)); -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; -#endif - - __skb_queue_head_init(&msdu_list); - -#ifdef CONFIG_SCSC_SMAPPER - /* Check if the payload is in the SMAPPER entry */ - if (fapi_get_u16(skb, u.ma_unitdata_ind.bulk_data_descriptor) == FAPI_BULKDATADESCRIPTOR_SMAPPER) { - /* Retrieve the associated smapper skb */ - skb = slsi_hip_get_skb_from_smapper(sdev, skb); - if (!skb) { - SLSI_NET_DBG2(dev, SLSI_RX, "SKB from SMAPPER is NULL\n"); - return; - } - } else { - /* strip signal and any signal/bulk roundings/offsets */ - skb_pull(skb, fapi_get_siglen(skb)); - } -#else - skb_pull(skb, fapi_get_siglen(skb)); -#endif - - eth_hdr = (struct ethhdr *)skb->data; - peer = slsi_get_peer_from_mac(sdev, dev, eth_hdr->h_source); - if (!peer) { - SLSI_NET_WARN(dev, "Packet dropped (no peer records)\n"); - slsi_kfree_skb(skb); - return; - } - - /* A-MSDU deaggregation */ - if (is_amsdu) { - if (slsi_rx_amsdu_deaggregate(dev, skb, &msdu_list)) { - ndev_vif->stats.rx_dropped++; - if (peer) - peer->sinfo.rx_dropped_misc++; - return; - } - } else { - __skb_queue_tail(&msdu_list, skb); - } - /* WARNING: skb may be NULL here and should not be used after this */ - while (!skb_queue_empty(&msdu_list)) { - struct sk_buff *rx_skb; - - rx_skb = __skb_dequeue(&msdu_list); - - /* In STA mode, the AP relays back our multicast traffic. - * Receiving these frames and passing it up confuses some - * protocols and applications, notably IPv6 Duplicate - * Address Detection. - * - * So these frames are dropped instead of passing it further. - * No need to update the drop statistics as these frames are - * locally generated and should not be accounted in reception. - */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) { - struct ethhdr *ehdr = (struct ethhdr *)(rx_skb->data); - - if (is_multicast_ether_addr(ehdr->h_dest) && - !compare_ether_addr(ehdr->h_source, dev->dev_addr)) { - SLSI_NET_DBG2(dev, SLSI_RX, "drop locally generated multicast frame relayed back by AP\n"); - slsi_kfree_skb(rx_skb); - continue; - } - } - - /* Intra BSS */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && ndev_vif->peer_sta_records) { - struct slsi_peer *peer = NULL; - struct ethhdr *ehdr = (struct ethhdr *)(rx_skb->data); - - if (is_multicast_ether_addr(ehdr->h_dest)) { -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - struct sk_buff *rebroadcast_skb = slsi_skb_copy(rx_skb, GFP_ATOMIC); -#else - struct sk_buff *rebroadcast_skb = slsi_skb_copy(rx_skb, GFP_KERNEL); -#endif - if (!rebroadcast_skb) { - SLSI_WARN(sdev, "Intra BSS: failed to alloc new SKB for broadcast\n"); - } else { - SLSI_DBG3(sdev, SLSI_RX, "Intra BSS: multicast %pM\n", ehdr->h_dest); - rebroadcast_skb->dev = dev; - rebroadcast_skb->protocol = cpu_to_be16(ETH_P_802_3); - slsi_dbg_untrack_skb(rebroadcast_skb); - skb_reset_network_header(rebroadcast_skb); - skb_reset_mac_header(rebroadcast_skb); - dev_queue_xmit(rebroadcast_skb); - } - } else { - peer = slsi_get_peer_from_mac(sdev, dev, ehdr->h_dest); - if (peer && peer->authorized) { - SLSI_DBG3(sdev, SLSI_RX, "Intra BSS: unicast %pM\n", ehdr->h_dest); - rx_skb->dev = dev; - rx_skb->protocol = cpu_to_be16(ETH_P_802_3); - slsi_dbg_untrack_skb(rx_skb); - skb_reset_network_header(rx_skb); - skb_reset_mac_header(rx_skb); - dev_queue_xmit(rx_skb); - continue; - } - } - } - - if (peer) { - peer->sinfo.rx_bytes += rx_skb->len; - } - ndev_vif->stats.rx_packets++; - ndev_vif->stats.rx_bytes += rx_skb->len; - ndev_vif->rx_packets[trafic_q]++; - -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - if (!ndev_vif->enhanced_arp_stats.is_duplicate_addr_detected) { - u8 *frame = rx_skb->data + 12; /* frame points to packet type */ - u16 packet_type = frame[0] << 8 | frame[1]; - - if (packet_type == ETH_P_ARP) { - frame = frame + 2; /* ARP packet */ - /*match source IP address in ARP with the DUT Ip address*/ - if ((frame[SLSI_ARP_SRC_IP_ADDR_OFFSET] == (ndev_vif->ipaddress & 255)) && - (frame[SLSI_ARP_SRC_IP_ADDR_OFFSET + 1] == ((ndev_vif->ipaddress >> 8U) & 255)) && - (frame[SLSI_ARP_SRC_IP_ADDR_OFFSET + 2] == ((ndev_vif->ipaddress >> 16U) & 255)) && - (frame[SLSI_ARP_SRC_IP_ADDR_OFFSET + 3] == ((ndev_vif->ipaddress >> 24U) & 255)) && - !SLSI_IS_GRATUITOUS_ARP(frame) && - !SLSI_ETHER_EQUAL(sdev->hw_addr, frame + 8)) /*if src MAC = DUT MAC */ - ndev_vif->enhanced_arp_stats.is_duplicate_addr_detected = 1; - } - } - - if (ndev_vif->enhanced_arp_detect_enabled && (ndev_vif->vif_type == FAPI_VIFTYPE_STATION)) { - u8 *frame = rx_skb->data + 12; /* frame points to packet type */ - u16 packet_type = frame[0] << 8 | frame[1]; - u16 arp_opcode; - - if (packet_type == ETH_P_ARP) { - frame = frame + 2; /* ARP packet */ - arp_opcode = frame[SLSI_ARP_OPCODE_OFFSET] << 8 | frame[SLSI_ARP_OPCODE_OFFSET + 1]; - /* check if sender ip = gateway ip and it is an ARP response */ - if ((arp_opcode == SLSI_ARP_REPLY_OPCODE) && - !SLSI_IS_GRATUITOUS_ARP(frame) && - !memcmp(&frame[SLSI_ARP_SRC_IP_ADDR_OFFSET], &ndev_vif->target_ip_addr, 4)) { - ndev_vif->enhanced_arp_stats.arp_rsp_count_to_netdev++; - ndev_vif->enhanced_arp_stats.arp_rsp_rx_count_by_upper_mac++; - } - } - } -#endif - - rx_skb->dev = dev; - rx_skb->ip_summed = CHECKSUM_NONE; - rx_skb->protocol = eth_type_trans(rx_skb, dev); - - SCSC_HIP4_SAMPLER_TCP_DECODE(sdev, dev, rx_skb->data, true); - slsi_traffic_mon_event_rx(sdev, dev, rx_skb); - slsi_dbg_untrack_skb(rx_skb); - - SLSI_DBG4(sdev, SLSI_RX, "pass %u bytes to local stack\n", rx_skb->len); -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); - if (conf_hip4_ver == 4) { -#ifdef CONFIG_SCSC_WLAN_RX_NAPI_GRO - if (!from_ba_timer) - napi_gro_receive(&sdev->hip4_inst.hip_priv->napi, rx_skb); - else - netif_receive_skb(rx_skb); -#else - netif_receive_skb(rx_skb); -#endif - } else { - netif_rx_ni(rx_skb); - } -#else - netif_rx_ni(rx_skb); -#endif - slsi_wakelock_timeout(&sdev->wlan_wl_ma, SLSI_RX_WAKELOCK_TIME); - } -} - -static void slsi_rx_data_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = NULL; - struct ethhdr *eth_hdr; - u16 seq_num; - - if (!((fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor) == FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME) || - (fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor) == FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME) || - (fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor) == FAPI_DATAUNITDESCRIPTOR_AMSDU))) { - WARN_ON(1); - slsi_kfree_skb(skb); - return; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - /* pass the data up "As is" if the VIF type is Monitor */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_MONITOR) { -#ifdef CONFIG_SCSC_SMAPPER - /* Check if the payload is in the SMAPPER entry */ - if (fapi_get_u16(skb, u.ma_unitdata_ind.bulk_data_descriptor) == FAPI_BULKDATADESCRIPTOR_SMAPPER) { - /* Retrieve the associated smapper skb */ - skb = slsi_hip_get_skb_from_smapper(sdev, skb); - if (!skb) { - SLSI_NET_DBG2(dev, SLSI_RX, "SKB from SMAPPER is NULL\n"); - return; - } - } else { - /* strip signal and any signal/bulk roundings/offsets */ - skb_pull(skb, fapi_get_siglen(skb)); - } -#else - skb_pull(skb, fapi_get_siglen(skb)); -#endif - skb_reset_mac_header(skb); - skb->dev = dev; - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->pkt_type = PACKET_OTHERHOST; - netif_rx_ni(skb); - return; - } -#endif - -#ifdef CONFIG_SCSC_SMAPPER - /* Check if the payload is in the SMAPPER entry */ - if (fapi_get_u16(skb, u.ma_unitdata_ind.bulk_data_descriptor) == FAPI_BULKDATADESCRIPTOR_SMAPPER) { - eth_hdr = (struct ethhdr *)slsi_hip_get_skb_data_from_smapper(sdev, skb); - if (!(eth_hdr)) { - SLSI_NET_DBG2(dev, SLSI_RX, "SKB from SMAPPER is NULL\n"); - slsi_kfree_skb(skb); - return; - } - } else { - eth_hdr = (struct ethhdr *)fapi_get_data(skb); - } -#else - eth_hdr = (struct ethhdr *)fapi_get_data(skb); -#endif - seq_num = fapi_get_u16(skb, u.ma_unitdata_ind.sequence_number); - SLSI_NET_DBG4(dev, SLSI_RX, "ma_unitdata_ind(vif:%d, dest:%pM, src:%pM, datatype:%d, priority:%d, s:%d)\n", - fapi_get_vif(skb), - eth_hdr->h_dest, - eth_hdr->h_source, - fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor), - fapi_get_u16(skb, u.ma_unitdata_ind.priority), - (seq_num & SLSI_RX_SEQ_NUM_MASK)); - - peer = slsi_get_peer_from_mac(sdev, dev, eth_hdr->h_source); - if (!peer) { - SLSI_NET_WARN(dev, "Packet dropped (no peer records)\n"); - /* Race in Data plane (Shows up in fw test mode) */ - slsi_kfree_skb(skb); - return; - } - - /* discard data frames if received before key negotiations are completed */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP && peer->connected_state != SLSI_STA_CONN_STATE_CONNECTED) { - SLSI_NET_WARN(dev, "Packet dropped (peer connection not complete (state:%u))\n", peer->connected_state); - slsi_kfree_skb(skb); - return; - } - - /* When TDLS connection has just been closed a few last frame may still arrive from the closed connection. - * This frames must not be injected in to the block session with the AP as the sequence numbers are different - * that will confuse the BA process. Therefore we have to skip BA for those frames. - */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION && peer->aid < SLSI_TDLS_PEER_INDEX_MIN && (seq_num & SLSI_RX_VIA_TDLS_LINK)) { - if (printk_ratelimit()) - SLSI_NET_WARN(dev, "Packet received from TDLS but no TDLS exists (seq: %x) Skip BA\n", seq_num); - - /* Skip BA reorder and pass the frames Up */ - slsi_rx_data_deliver_skb(sdev, dev, skb, false); - return; - } - - /* TDLS is enabled for the PEER but still packet is received through the AP. Process this packet with the AP PEER */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_STATION && peer->aid >= SLSI_TDLS_PEER_INDEX_MIN && (!(seq_num & SLSI_RX_VIA_TDLS_LINK))) { - SLSI_NET_DBG2(dev, SLSI_TDLS, "Packet received from TDLS peer through the AP(seq: %x)\n", seq_num); - peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - if (!peer) { - SLSI_NET_WARN(dev, "Packet dropped (AP peer not found)\n"); - slsi_kfree_skb(skb); - return; - } - } - - /* If frame belongs to a negotiated BA, BA will consume the frame */ - if (slsi_ba_check(peer, fapi_get_u16(skb, u.ma_unitdata_ind.priority))) - if (!slsi_ba_process_frame(dev, peer, skb, (seq_num & SLSI_RX_SEQ_NUM_MASK), - fapi_get_u16(skb, u.ma_unitdata_ind.priority))) - return; - - /* Pass to next receive process */ - slsi_rx_data_deliver_skb(sdev, dev, skb, false); -} - -static int slsi_rx_data_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - u16 host_tag = fapi_get_u16(skb, u.ma_unitdata_cfm.host_tag); - - SLSI_NET_DBG1(dev, SLSI_TX, "ma_unitdata_cfm(vif:%d, host_tag:0x%x, status:%d)\n", - fapi_get_vif(skb), - host_tag, - fapi_get_u16(skb, u.ma_unitdata_cfm.transmission_status)); -#ifdef CONFIG_SCSC_WLAN_DEBUG - if (fapi_get_u16(skb, u.ma_unitdata_cfm.transmission_status) == FAPI_TRANSMISSIONSTATUS_TX_LIFETIME) { - if (printk_ratelimit()) - SLSI_NET_WARN(dev, "ma_unitdata_cfm: tx_lifetime(vif:%d, host_tag:0x%x)\n", fapi_get_vif(skb), host_tag); - } -#endif - if (fapi_get_u16(skb, u.ma_unitdata_cfm.transmission_status) == FAPI_TRANSMISSIONSTATUS_RETRY_LIMIT) - ndev_vif->tx_no_ack[SLSI_HOST_TAG_TRAFFIC_QUEUE(host_tag)]++; - - slsi_kfree_skb(skb); - return 0; -} - -#ifdef CONFIG_SCSC_WLAN_RX_NAPI -static int slsi_rx_napi_process(struct slsi_dev *sdev, struct sk_buff *skb) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - u16 vif; - - vif = fapi_get_vif(skb); - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (!dev) { - SLSI_ERR(sdev, "netdev(%d) No longer exists\n", vif); - rcu_read_unlock(); - return -EINVAL; - } - rcu_read_unlock(); - - ndev_vif = netdev_priv(dev); - - switch (fapi_get_u16(skb, id)) { - case MA_UNITDATA_IND: - slsi_rx_data_ind(sdev, dev, skb); - - /* SKBs in a BA session are not passed yet */ - if (atomic_read(&ndev_vif->ba_flush)) { - atomic_set(&ndev_vif->ba_flush, 0); - slsi_ba_process_complete(dev, false); - } - break; - case MA_UNITDATA_CFM: - (void)slsi_rx_data_cfm(sdev, dev, skb); - break; - default: - SLSI_DBG1(sdev, SLSI_RX, "Unexpected Data: 0x%.4x\n", fapi_get_sigid(skb)); - slsi_kfree_skb(skb); - break; - } - return 0; -} -#endif -void slsi_rx_netdev_data_work(struct work_struct *work) -{ - struct slsi_skb_work *w = container_of(work, struct slsi_skb_work, work); - struct slsi_dev *sdev = w->sdev; - struct net_device *dev = w->dev; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *skb; - - if (WARN_ON(!dev)) - return; - - slsi_wakelock(&sdev->wlan_wl); - - while (1) { - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - slsi_skb_queue_purge(&w->queue); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - break; - } - - if (atomic_read(&ndev_vif->ba_flush)) { - atomic_set(&ndev_vif->ba_flush, 0); - slsi_ba_process_complete(dev, false); - } - - skb = slsi_skb_work_dequeue(w); - if (!skb) { - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - break; - } - - switch (fapi_get_u16(skb, id)) { - case MA_UNITDATA_IND: -#ifdef CONFIG_SCSC_SMAPPER - if (fapi_get_u16(skb, u.ma_unitdata_ind.bulk_data_descriptor) == FAPI_BULKDATADESCRIPTOR_SMAPPER) { - u8 *frame = (u8 *)slsi_hip_get_skb_data_from_smapper(sdev, skb); - - if (frame) - SCSC_HIP4_SAMPLER_TCP_DECODE(sdev, dev, frame, false); - } else { - SCSC_HIP4_SAMPLER_TCP_DECODE(sdev, dev, skb->data + fapi_get_siglen(skb), false); - } -#else - SCSC_HIP4_SAMPLER_TCP_DECODE(sdev, dev, skb->data + fapi_get_siglen(skb), false); -#endif - slsi_rx_data_ind(sdev, dev, skb); - break; - case MA_UNITDATA_CFM: - (void)slsi_rx_data_cfm(sdev, dev, skb); - break; - default: - SLSI_DBG1(sdev, SLSI_RX, "Unexpected Data: 0x%.4x\n", fapi_get_sigid(skb)); - slsi_kfree_skb(skb); - break; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } - slsi_wakeunlock(&sdev->wlan_wl); -} - -static int slsi_rx_queue_data(struct slsi_dev *sdev, struct sk_buff *skb) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - int vif; - - vif = fapi_get_vif(skb); - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (!dev) { - SLSI_ERR(sdev, "netdev(%d) No longer exists\n", vif); - rcu_read_unlock(); - goto err; - } - ndev_vif = netdev_priv(dev); - - slsi_skb_work_enqueue(&ndev_vif->rx_data, skb); - rcu_read_unlock(); - return 0; -err: - return -EINVAL; -} - -static int sap_ma_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb) -{ -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - u32 conf_hip4_ver = 0; -#endif -#ifdef CONFIG_SCSC_SMAPPER - u16 sig_len; - u32 err; -#endif - - switch (fapi_get_sigid(skb)) { - case MA_UNITDATA_IND: -#ifdef CONFIG_SCSC_SMAPPER - /* Check SMAPPER to nullify entry*/ - if (fapi_get_u16(skb, u.ma_unitdata_ind.bulk_data_descriptor) == FAPI_BULKDATADESCRIPTOR_SMAPPER) { - sig_len = fapi_get_siglen(skb); - skb_pull(skb, sig_len); - err = slsi_hip_consume_smapper_entry(sdev, skb); - skb_push(skb, sig_len); - if (err) - return err; - } -#endif - case MA_UNITDATA_CFM: -#ifdef CONFIG_SCSC_WLAN_RX_NAPI - conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); - if (conf_hip4_ver == 4) - return slsi_rx_napi_process(sdev, skb); - else - return slsi_rx_queue_data(sdev, skb); -#else - return slsi_rx_queue_data(sdev, skb); -#endif - case MA_BLOCKACK_IND: - /* It is anomolous to handle the MA_BLOCKACK_IND in the - * mlme wq. - */ - return slsi_rx_enqueue_netdev_mlme(sdev, skb, fapi_get_vif(skb)); - default: - break; - } - - SLSI_ERR_NODEV("Shouldn't be getting here!\n"); - return -EINVAL; -} - -/* Adjust the scod value and flow control appropriately. */ -static int sap_ma_txdone(struct slsi_dev *sdev, u16 colour) -{ - struct net_device *dev; - struct slsi_peer *peer; - u16 vif, peer_index, ac; - - /* Extract information from the coloured mbulk */ - /* colour is defined as: */ - /* u16 register bits: - * 0 - do not use - * [2:1] - vif - * [7:3] - peer_index - * [10:8] - ac queue - */ - vif = (colour & 0x6) >> 1; - peer_index = (colour & 0xf8) >> 3; - ac = (colour & 0x300) >> 8; - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - - if (!dev) { - SLSI_ERR(sdev, "netdev(%d) No longer exists\n", vif); - rcu_read_unlock(); - return -EINVAL; - } - rcu_read_unlock(); - - if (peer_index <= SLSI_PEER_INDEX_MAX) { - /* peer_index = 0 for Multicast queues */ - if (peer_index == 0) { - struct netdev_vif *ndev_vif = netdev_priv(dev); - - return scsc_wifi_fcq_receive_data(dev, &ndev_vif->ap.group_data_qs, ac, sdev, vif, peer_index); - } - peer = slsi_get_peer_from_qs(sdev, dev, MAP_AID_TO_QS(peer_index)); - if (peer) - return scsc_wifi_fcq_receive_data(dev, &peer->data_qs, ac, sdev, vif, peer_index); - - SLSI_DBG3(sdev, SLSI_RX, "peer record NOT found for peer_index=%d\n", peer_index); - /* We need to handle this case as special. Peer disappeared bug hip4 - * is sending back the colours to free. - */ - return scsc_wifi_fcq_receive_data_no_peer(dev, ac, sdev, vif, peer_index); - } - SLSI_ERR(sdev, "illegal peer_index vif=%d peer_index=%d\n", vif, peer_index); - return -EINVAL; -} - -int sap_ma_init(void) -{ - SLSI_INFO_NODEV("Registering SAP\n"); - slsi_hip_sap_register(&sap_ma); - return 0; -} - -int sap_ma_deinit(void) -{ - SLSI_INFO_NODEV("Unregistering SAP\n"); - slsi_hip_sap_unregister(&sap_ma); - return 0; -} diff --git a/drivers/net/wireless/scsc/sap_ma.h b/drivers/net/wireless/scsc/sap_ma.h deleted file mode 100644 index 2cb5bf97ada1..000000000000 --- a/drivers/net/wireless/scsc/sap_ma.h +++ /dev/null @@ -1,14 +0,0 @@ - -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SAP_MA_H__ -#define __SAP_MA_H__ - -int sap_ma_init(void); -int sap_ma_deinit(void); - -#endif diff --git a/drivers/net/wireless/scsc/sap_mlme.c b/drivers/net/wireless/scsc/sap_mlme.c deleted file mode 100755 index 942c6a7ac940..000000000000 --- a/drivers/net/wireless/scsc/sap_mlme.c +++ /dev/null @@ -1,434 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include "debug.h" -#include "dev.h" -#include "sap.h" -#include "sap_mlme.h" -#include "hip.h" -#include "mgt.h" - -#ifdef CONFIG_ANDROID -#include "scsc_wifilogger_rings.h" -#endif -#include "nl80211_vendor.h" -#include "mlme.h" - -#define SUPPORTED_OLD_VERSION 0 - -static int sap_mlme_version_supported(u16 version); -static int sap_mlme_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb); - -static int sap_mlme_notifier(struct slsi_dev *sdev, unsigned long event); - -static struct sap_api sap_mlme = { - .sap_class = SAP_MLME, - .sap_version_supported = sap_mlme_version_supported, - .sap_handler = sap_mlme_rx_handler, - .sap_versions = { FAPI_CONTROL_SAP_VERSION, SUPPORTED_OLD_VERSION }, - .sap_notifier = sap_mlme_notifier, -}; - -static int sap_mlme_notifier(struct slsi_dev *sdev, unsigned long event) -{ - int i; -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - struct net_device *dev; -#endif - struct netdev_vif *ndev_vif; - - SLSI_INFO_NODEV("Notifier event received: %lu\n", event); - if (event >= SCSC_MAX_NOTIFIER) - return -EIO; - - switch (event) { - case SCSC_WIFI_STOP: - /* Stop sending signals down*/ - sdev->mlme_blocked = true; - SLSI_INFO_NODEV("MLME BLOCKED\n"); - - /* cleanup all the VIFs and scan data */ - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - complete_all(&sdev->sig_wait.completion); - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) - if (sdev->netdev[i]) { - ndev_vif = netdev_priv(sdev->netdev[i]); - slsi_scan_cleanup(sdev, sdev->netdev[i]); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - slsi_vif_cleanup(sdev, sdev->netdev[i], 0); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - SLSI_INFO_NODEV("Force cleaned all VIFs\n"); - break; - - case SCSC_WIFI_FAILURE_RESET: - break; - - case SCSC_WIFI_SUSPEND: - break; - - case SCSC_WIFI_RESUME: -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if ((ndev_vif->is_wips_running) && (ndev_vif->activated) && - (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) && - (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - ndev_vif->is_wips_running = false; - - slsi_send_forward_beacon_abort_vendor_event(sdev, SLSI_FORWARD_BEACON_ABORT_REASON_SUSPENDED); - SLSI_INFO_NODEV("FORWARD_BEACON: SUSPEND_RESUMED!! send abort event\n"); - } - - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -#endif - break; - - default: - SLSI_INFO_NODEV("Unknown event code %lu\n", event); - break; - } - - return 0; -} - -static int sap_mlme_version_supported(u16 version) -{ - unsigned int major = SAP_MAJOR(version); - unsigned int minor = SAP_MINOR(version); - u8 i = 0; - - SLSI_INFO_NODEV("Reported version: %d.%d\n", major, minor); - - for (i = 0; i < SAP_MAX_VER; i++) - if (SAP_MAJOR(sap_mlme.sap_versions[i]) == major) - return 0; - - SLSI_ERR_NODEV("Version %d.%d Not supported\n", major, minor); - - return -EINVAL; -} - -static int slsi_rx_netdev_mlme(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 id = fapi_get_u16(skb, id); - - /* The skb is consumed by the functions called. - */ - switch (id) { - case MLME_SCAN_IND: - slsi_rx_scan_ind(sdev, dev, skb); - break; - case MLME_SCAN_DONE_IND: - slsi_rx_scan_done_ind(sdev, dev, skb); - break; - case MLME_CONNECT_IND: - slsi_rx_connect_ind(sdev, dev, skb); - break; - case MLME_CONNECTED_IND: - slsi_rx_connected_ind(sdev, dev, skb); - break; - case MLME_RECEIVED_FRAME_IND: - slsi_rx_received_frame_ind(sdev, dev, skb); - break; - case MLME_DISCONNECT_IND: - slsi_rx_disconnect_ind(sdev, dev, skb); - break; - case MLME_DISCONNECTED_IND: - slsi_rx_disconnected_ind(sdev, dev, skb); - break; - case MLME_PROCEDURE_STARTED_IND: - slsi_rx_procedure_started_ind(sdev, dev, skb); - break; - case MLME_FRAME_TRANSMISSION_IND: - slsi_rx_frame_transmission_ind(sdev, dev, skb); - break; - case MA_BLOCKACK_IND: - slsi_rx_blockack_ind(sdev, dev, skb); - break; - case MLME_ROAMED_IND: - slsi_rx_roamed_ind(sdev, dev, skb); - break; - case MLME_ROAM_IND: - slsi_rx_roam_ind(sdev, dev, skb); - break; - case MLME_MIC_FAILURE_IND: - slsi_rx_mic_failure_ind(sdev, dev, skb); - break; - case MLME_REASSOCIATE_IND: - slsi_rx_reassoc_ind(sdev, dev, skb); - break; - case MLME_TDLS_PEER_IND: - slsi_tdls_peer_ind(sdev, dev, skb); - break; - case MLME_LISTEN_END_IND: - slsi_rx_listen_end_ind(dev, skb); - break; - case MLME_CHANNEL_SWITCHED_IND: - slsi_rx_channel_switched_ind(sdev, dev, skb); - break; - case MLME_AC_PRIORITY_UPDATE_IND: - SLSI_DBG1(sdev, SLSI_MLME, "Unexpected MLME_AC_PRIORITY_UPDATE_IND\n"); - slsi_kfree_skb(skb); - break; -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - case MLME_RSSI_REPORT_IND: - slsi_rx_rssi_report_ind(sdev, dev, skb); - break; - case MLME_RANGE_IND: - slsi_rx_range_ind(sdev, dev, skb); - break; - case MLME_RANGE_DONE_IND: - slsi_rx_range_done_ind(sdev, dev, skb); - break; - case MLME_EVENT_LOG_IND: - slsi_rx_event_log_indication(sdev, dev, skb); - break; -#endif -#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE - case MLME_NAN_EVENT_IND: - slsi_nan_event(sdev, dev, skb); - slsi_kfree_skb(skb); - break; - case MLME_NAN_FOLLOWUP_IND: - slsi_nan_followup_ind(sdev, dev, skb); - slsi_kfree_skb(skb); - break; - case MLME_NAN_SERVICE_IND: - slsi_nan_service_ind(sdev, dev, skb); - slsi_kfree_skb(skb); - break; -#endif -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG - case MLME_SYNCHRONISED_IND: - slsi_rx_synchronised_ind(sdev, dev, skb); - slsi_kfree_skb(skb); - break; -#endif -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON - case MLME_BEACON_REPORTING_EVENT_IND: - slsi_rx_beacon_reporting_event_ind(sdev, dev, skb); - break; -#endif - default: - slsi_kfree_skb(skb); - SLSI_NET_ERR(dev, "Unhandled Ind: 0x%.4x\n", id); - break; - } - return 0; -} - -void slsi_rx_netdev_mlme_work(struct work_struct *work) -{ - struct slsi_skb_work *w = container_of(work, struct slsi_skb_work, work); - struct slsi_dev *sdev = w->sdev; - struct net_device *dev = w->dev; - struct sk_buff *skb = slsi_skb_work_dequeue(w); - - if (WARN_ON(!dev)) - return; - - slsi_wakelock(&sdev->wlan_wl); - while (skb) { - slsi_debug_frame(sdev, dev, skb, "RX"); - slsi_rx_netdev_mlme(sdev, dev, skb); - skb = slsi_skb_work_dequeue(w); - } - slsi_wakeunlock(&sdev->wlan_wl); -} - -int slsi_rx_enqueue_netdev_mlme(struct slsi_dev *sdev, struct sk_buff *skb, u16 vif) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (WARN_ON(!dev)) { - rcu_read_unlock(); - /* Calling function should free the skb */ - return -ENODEV; - } - - ndev_vif = netdev_priv(dev); - - if (unlikely(ndev_vif->is_fw_test)) { - slsi_kfree_skb(skb); - rcu_read_unlock(); - return 0; - } - - slsi_skb_work_enqueue(&ndev_vif->rx_mlme, skb); - rcu_read_unlock(); - return 0; -} - -static int slsi_rx_action_enqueue_netdev_mlme(struct slsi_dev *sdev, struct sk_buff *skb, u16 vif) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (WARN_ON(!dev)) { - rcu_read_unlock(); - return -ENODEV; - } - - ndev_vif = netdev_priv(dev); - - if (unlikely(ndev_vif->is_fw_test)) { - rcu_read_unlock(); - return 0; - } - - if (ndev_vif->iftype == NL80211_IFTYPE_P2P_GO || ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) { - struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb); - /* Check the DA of received action frame with the GO interface address */ - if (memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) != 0) { - /* If not equal, compare DA of received action frame with the P2P DEV address*/ - struct net_device *p2pdev = slsi_get_netdev_rcu(sdev, SLSI_NET_INDEX_P2P); - - if (WARN_ON(!p2pdev)) { - rcu_read_unlock(); - return -ENODEV; - } - if (memcmp(mgmt->da, p2pdev->dev_addr, ETH_ALEN) == 0) { - /* If destination address is equal to P2P DEV ADDR, then action frame is received on - * GO interface. Hence indicate action frames on P2P DEV - */ - ndev_vif = netdev_priv(p2pdev); - - if (unlikely(ndev_vif->is_fw_test)) { - slsi_kfree_skb(skb); - rcu_read_unlock(); - return 0; - } - } - } - } - - slsi_skb_work_enqueue(&ndev_vif->rx_mlme, skb); - - rcu_read_unlock(); - return 0; -} - -static int sap_mlme_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb) -{ - u16 scan_id; - u16 vif = fapi_get_vif(skb); - - if (slsi_rx_blocking_signals(sdev, skb) == 0) - return 0; - - if (fapi_is_ind(skb)) { -#ifdef CONFIG_SCSC_WIFILOGGER - SCSC_WLOG_PKTFATE_LOG_RX_CTRL_FRAME(fapi_get_data(skb), fapi_get_datalen(skb)); -#endif - - switch (fapi_get_sigid(skb)) { - case MLME_SCAN_DONE_IND: - scan_id = fapi_get_u16(skb, u.mlme_scan_done_ind.scan_id); -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - if (slsi_is_gscan_id(scan_id)) - return slsi_rx_enqueue_netdev_mlme(sdev, skb, SLSI_NET_INDEX_WLAN); -#endif - return slsi_rx_enqueue_netdev_mlme(sdev, skb, (scan_id >> 8)); - case MLME_SCAN_IND: - if (vif) - return slsi_rx_enqueue_netdev_mlme(sdev, skb, vif); - scan_id = fapi_get_u16(skb, u.mlme_scan_ind.scan_id); -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - if (slsi_is_gscan_id(scan_id)) - return slsi_rx_enqueue_netdev_mlme(sdev, skb, SLSI_NET_INDEX_WLAN); -#endif - return slsi_rx_enqueue_netdev_mlme(sdev, skb, (scan_id >> 8)); - case MLME_RECEIVED_FRAME_IND: - if (vif == 0) { - SLSI_WARN(sdev, "Received MLME_RECEIVED_FRAME_IND on VIF 0\n"); - goto err; - } - return slsi_rx_action_enqueue_netdev_mlme(sdev, skb, vif); -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE - case MLME_NAN_EVENT_IND: - case MLME_NAN_FOLLOWUP_IND: - case MLME_NAN_SERVICE_IND: - return slsi_rx_enqueue_netdev_mlme(sdev, skb, vif); - case MLME_RANGE_IND: - case MLME_RANGE_DONE_IND: - if (vif == 0) - return slsi_rx_enqueue_netdev_mlme(sdev, skb, SLSI_NET_INDEX_WLAN); - else - return slsi_rx_enqueue_netdev_mlme(sdev, skb, vif); -#endif -#ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING - case MLME_EVENT_LOG_IND: - return slsi_rx_enqueue_netdev_mlme(sdev, skb, SLSI_NET_INDEX_WLAN); -#endif - case MLME_ROAMED_IND: - if (vif == 0) { - SLSI_WARN(sdev, "Received MLME_ROAMED_IND on VIF 0, return error\n"); - goto err; - } else { - struct net_device *dev; - struct netdev_vif *ndev_vif; - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (WARN_ON(!dev)) { - rcu_read_unlock(); - return -ENODEV; - } - ndev_vif = netdev_priv(dev); - if (atomic_read(&ndev_vif->sta.drop_roamed_ind)) { - /* If roam cfm is not received for the req, ignore this roamed indication. */ - slsi_kfree_skb(skb); - rcu_read_unlock(); - return 0; - } - rcu_read_unlock(); - return slsi_rx_enqueue_netdev_mlme(sdev, skb, vif); - } - default: - if (vif == 0) { - SLSI_WARN(sdev, "Received signal 0x%04x on VIF 0, return error\n", fapi_get_sigid(skb)); - goto err; - } else { - return slsi_rx_enqueue_netdev_mlme(sdev, skb, vif); - } - } - } - if (WARN_ON(fapi_is_req(skb))) - goto err; - - if (slsi_is_test_mode_enabled()) { - slsi_kfree_skb(skb); - return 0; - } - - WARN_ON(1); - -err: - return -EINVAL; -} - -int sap_mlme_init(void) -{ - SLSI_INFO_NODEV("Registering SAP\n"); - slsi_hip_sap_register(&sap_mlme); - return 0; -} - -int sap_mlme_deinit(void) -{ - SLSI_INFO_NODEV("Unregistering SAP\n"); - slsi_hip_sap_unregister(&sap_mlme); - return 0; -} diff --git a/drivers/net/wireless/scsc/sap_mlme.h b/drivers/net/wireless/scsc/sap_mlme.h deleted file mode 100755 index e2c95fb0e0c2..000000000000 --- a/drivers/net/wireless/scsc/sap_mlme.h +++ /dev/null @@ -1,39 +0,0 @@ - -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SAP_MLME_H__ -#define __SAP_MLME_H__ - -int sap_mlme_init(void); -int sap_mlme_deinit(void); - -/* MLME signal handlers in rx.c */ -void slsi_rx_scan_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON -void slsi_rx_beacon_reporting_event_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -#endif -void slsi_rx_scan_done_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_channel_switched_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG -void slsi_rx_synchronised_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -#endif -void slsi_rx_connect_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_received_frame_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_disconnect_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_disconnected_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_procedure_started_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_frame_transmission_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_roamed_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_roam_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_mic_failure_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_reassoc_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_tdls_peer_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_listen_end_ind(struct net_device *dev, struct sk_buff *skb); -void slsi_rx_blockack_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); - -#endif diff --git a/drivers/net/wireless/scsc/sap_test.c b/drivers/net/wireless/scsc/sap_test.c deleted file mode 100644 index 403368337c90..000000000000 --- a/drivers/net/wireless/scsc/sap_test.c +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include "dev.h" -#include "sap.h" -#include "sap_test.h" -#include "hip.h" - -#include "debug.h" - -#define SUPPORTED_OLD_VERSION 0 - -static int sap_test_version_supported(u16 version); -static int sap_test_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb); - -static struct sap_api sap_test = { - .sap_class = SAP_TST, - .sap_version_supported = sap_test_version_supported, - .sap_handler = sap_test_rx_handler, - .sap_versions = { FAPI_TEST_SAP_VERSION, SUPPORTED_OLD_VERSION }, -}; - -static int sap_test_version_supported(u16 version) -{ - unsigned int major = SAP_MAJOR(version); - unsigned int minor = SAP_MINOR(version); - u8 i = 0; - - SLSI_INFO_NODEV("Reported version: %d.%d\n", major, minor); - - for (i = 0; i < SAP_MAX_VER; i++) - if (SAP_MAJOR(sap_test.sap_versions[i]) == major) - return 0; - - SLSI_ERR_NODEV("Version %d.%d Not supported\n", major, minor); - - return -EINVAL; -} - -static int sap_test_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb) -{ - if (slsi_rx_blocking_signals(sdev, skb) == 0) - return 0; - - SLSI_INFO_NODEV("TEST SAP not implemented\n"); - /* Silently consume the skb */ - slsi_kfree_skb(skb); - /* return success */ - return 0; -} - -int sap_test_init(void) -{ - SLSI_INFO_NODEV("Registering SAP\n"); - slsi_hip_sap_register(&sap_test); - return 0; -} - -int sap_test_deinit(void) -{ - SLSI_INFO_NODEV("Unregistering SAP\n"); - slsi_hip_sap_unregister(&sap_test); - return 0; -} diff --git a/drivers/net/wireless/scsc/sap_test.h b/drivers/net/wireless/scsc/sap_test.h deleted file mode 100644 index 0b4c5dae8544..000000000000 --- a/drivers/net/wireless/scsc/sap_test.h +++ /dev/null @@ -1,14 +0,0 @@ - -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SAP_TEST_H__ -#define __SAP_TEST_H__ - -int sap_test_init(void); -int sap_test_deinit(void); - -#endif diff --git a/drivers/net/wireless/scsc/scsc_wifi_cm_if.h b/drivers/net/wireless/scsc/scsc_wifi_cm_if.h deleted file mode 100755 index a1ee9a146f73..000000000000 --- a/drivers/net/wireless/scsc/scsc_wifi_cm_if.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SCSC_WIFI_CM_IF_H__ -#define __SCSC_WIFI_CM_IF_H__ - -#include -#include -#include - -#include - -struct slsi_dev; - -/** - * CM interface States: - * STOPPED : (default) state, - * PROBING : - * PROBED : - * STARTING : - * STARTED : - * STOPPING : - * REMOVING : - * REMOVED : - * BLOCKED : - */ -enum scsc_wifi_cm_if_state { - SCSC_WIFI_CM_IF_STATE_STOPPED, - SCSC_WIFI_CM_IF_STATE_PROBING, - SCSC_WIFI_CM_IF_STATE_PROBED, - SCSC_WIFI_CM_IF_STATE_STARTING, - SCSC_WIFI_CM_IF_STATE_STARTED, - SCSC_WIFI_CM_IF_STATE_STOPPING, - SCSC_WIFI_CM_IF_STATE_REMOVING, - SCSC_WIFI_CM_IF_STATE_REMOVED, - SCSC_WIFI_CM_IF_STATE_BLOCKED -}; - -/** - * Notification Events - * SCSC_WIFI_STOP : Wifi service should freeze - * SCSC_WIFI_FAILURE_RESET : Failure has been handled - * SCSC_WIFI_SUSPEND: Host going in to suspend mode - * SCSC_WIFI_RESUME: Host resuming - */ -enum scsc_wifi_cm_if_notifier { - SCSC_WIFI_STOP, - SCSC_WIFI_FAILURE_RESET, - SCSC_WIFI_SUSPEND, - SCSC_WIFI_RESUME, - SCSC_MAX_NOTIFIER -}; - -struct scsc_wifi_cm_if { - struct slsi_dev *sdev; - /* a std mutex */ - struct mutex cm_if_mutex; - - struct kref kref; - - /* refer to enum scsc_wifi_cm_if_state */ - atomic_t cm_if_state; -}; - -/*********************************** API ************************************/ - -/** - * Driver's interface to cm_if - */ -struct slsi_dev *slsi_dev_attach(struct device *dev, struct scsc_mx *core, struct scsc_service_client *mx_wlan_client); -void slsi_dev_detach(struct slsi_dev *sdev); - -/** - * cm_if's interface to driver - */ -int slsi_sm_service_driver_register(void); -void slsi_sm_service_driver_unregister(void); -void slsi_sm_service_failed(struct slsi_dev *sdev, const char *reason); -int slsi_sm_wlan_service_open(struct slsi_dev *sdev); -int slsi_sm_wlan_service_start(struct slsi_dev *sdev); -void slsi_sm_wlan_service_stop(struct slsi_dev *sdev); -void slsi_sm_wlan_service_close(struct slsi_dev *sdev); -int slsi_wlan_service_notifier_register(struct notifier_block *nb); -int slsi_wlan_service_notifier_unregister(struct notifier_block *nb); - -#endif diff --git a/drivers/net/wireless/scsc/scsc_wifi_fcq.c b/drivers/net/wireless/scsc/scsc_wifi_fcq.c deleted file mode 100755 index cb8e25228f16..000000000000 --- a/drivers/net/wireless/scsc/scsc_wifi_fcq.c +++ /dev/null @@ -1,1177 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include "scsc_wifi_fcq.h" -#include "debug.h" -#include "dev.h" -#include "hip4_sampler.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) -#include "porting_imx.h" -#endif - -/* Queues hierarchy and control domains - * - * wlan p2p p2pX - * | | | - * | | | - * | | | - * | | | - * -------------------------------------- - * | - * \ Global domain - * | - * | - * ---------------------------------------- - * | | ... | - * | | ... | Smod Domain (vid, peer_id) - * \ \ ... \ - * | | ... | - * | | ... | - * ------------------------------------------------------ - * | | | | | | | | ... | | | | - * \ \ \ \ \ \ \ \ ... \ \ \ \ Qmod Domain - * | | | | | | | | ... | | | | - * ----------------------------------------------------- - * vi vo bk be vi vo bk be vi vo bk be - */ - -uint scsc_wifi_fcq_smod = 400; -module_param(scsc_wifi_fcq_smod, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_smod, "Initial value of unicast smod - peer normal (default = 400)"); - -uint scsc_wifi_fcq_mcast_smod = 100; -module_param(scsc_wifi_fcq_mcast_smod, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_mcast_smod, "Initial value of multicast smod - peer normal (default = 100)"); - -uint scsc_wifi_fcq_smod_power = 4; -module_param(scsc_wifi_fcq_smod_power, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_smod_power, "Initial powersave SMOD value - peer powersave (default = 4)"); - -uint scsc_wifi_fcq_mcast_smod_power = 4; -module_param(scsc_wifi_fcq_mcast_smod_power, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_mcast_smod_power, "Initial value of powersave multicast smod - peer normal (default = 4)"); - -uint scsc_wifi_fcq_qmod = 400; -module_param(scsc_wifi_fcq_qmod, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_qmod, "Initial value of unicast qmod - peer normal (default = 400)"); - -uint scsc_wifi_fcq_mcast_qmod = 100; -module_param(scsc_wifi_fcq_mcast_qmod, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_mcast_qmod, "Initial value of multicast qmod - peer normal (default = 100)"); - -uint scsc_wifi_fcq_minimum_smod = 50; -module_param(scsc_wifi_fcq_minimum_smod, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_minimum_smod, "Initial value of minimum smod - peer normal (default = 50)"); - -uint scsc_wifi_fcq_distribution_delay_ms; -module_param(scsc_wifi_fcq_distribution_delay_ms, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(scsc_wifi_fcq_distribution_delay_ms, "Distribution time in ms (default = 0)"); - -#define SCSC_WIFI_FCQ_SMOD_RESUME_HYSTERESIS 10 -#define SCSC_WIFI_FCQ_QMOD_RESUME_HYSTERESIS 10 -#define SCSC_WIFI_FCQ_GMOD_RESUME_HYSTERESIS 30 - -/* Protection guard before reaching Stop queues. */ -#define STOP_GUARD_GMOD 10 -#define STOP_GUARD_SMOD 1 -#define STOP_GUARD_QMOD 2 - -/* CLOSE_IN_OVERSHOOT could close the overshooted queues quickly, however could lead to ENOSPC on */ -/* a multithreaded environment */ -/* #define CLOSE_IN_OVERSHOOT 1 */ - -/* To optimally start/stop global queues */ -struct peers_cache { - struct list_head list; - struct net_device *dev; - int vif; - int peer_index; - struct scsc_wifi_fcq_data_qset *qs; - bool is_unicast; -}; - -static LIST_HEAD(peers_cache_list); -static DEFINE_SPINLOCK(peers_cache_lock); - -/* AC qmod mapping */ -/* 0 - indicates not active */ -/* > 0 - indicates active and the qmod value */ -static u32 ac_q_layout[8][4] = { - { 0, 0, 0, 1000}, - { 0, 0, 500, 500}, - { 0, 500, 0, 500}, - { 0, 333, 333, 333}, - { 500, 0, 0, 500}, - { 333, 0, 333, 333}, - { 333, 333, 0, 333}, - { 250, 250, 250, 250}, -}; - -/* Setting ENABLE_QCOD will include a second layer of flow control calculation for a specific queue. - * #define ENABLE_QCOD 1 - */ -#define ENABLE_QCOD 1 -#ifdef CONFIG_SCSC_DEBUG -/* Global debug counters */ -#define DOMAINS 3 -#define DOMAIN_G 0 -#define DOMAIN_S 1 -#define DOMAIN_Q 2 - -#define DIREC 2 -#define DIREC_TX 0 -#define DIREC_RX 1 - -#define AC_Q 4 - -static int td[DIREC][DOMAINS][AC_Q]; - -static inline void fcq_update_counters(int direction, int domain, int ac) -{ - td[direction][domain][ac] = td[direction][domain][ac] + 1; -} -#endif - -/* Setting ENABLE_CTRL_FCQ will include flow control on control queues. - * #define ENABLE_CTRL_FCQ 1 - */ - -/* POC */ -static int total; - -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION -/* Need to track the number of peer in smod */ -static int total_in_sleep; -#endif - -static inline bool is_gmod_active(struct slsi_dev *sdev) -{ - return atomic_read(&sdev->hip4_inst.hip_priv->gactive); -} - -static inline bool is_smod_active(struct scsc_wifi_fcq_data_qset *qs) -{ - return atomic_read(&qs->active); -} - -static inline bool is_qmod_active(struct scsc_wifi_fcq_data_q *queue) -{ - return atomic_read(&queue->head.active); -} - -static inline bool is_in_pause(struct slsi_dev *sdev) -{ - return atomic_read(&sdev->in_pause_state); -} - -/* Should be called from locked context */ -static inline void fcq_stop_all_queues(struct slsi_dev *sdev) -{ - int i; - struct peers_cache *pc_node, *next; - spin_lock_bh(&peers_cache_lock); - list_for_each_entry_safe(pc_node, next, &peers_cache_list, list) { - /* Stop queues all queues */ - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "fcq_stop_all_queues vif %d peer_index %d ac %d\n", pc_node->vif, pc_node->peer_index, i); - netif_stop_subqueue(pc_node->dev, pc_node->qs->ac_q[i].head.netif_queue_id); - } - } - spin_unlock_bh(&peers_cache_lock); -} - -/* Should be called from locked context */ -static inline void fcq_wake_all_queues(struct slsi_dev *sdev) -{ - int i; - struct peers_cache *pc_node, *next; - - spin_lock_bh(&peers_cache_lock); - list_for_each_entry_safe(pc_node, next, &peers_cache_list, list) { - /* Wake queues that reported to be active, leave stopped the others. Do not wake queues in pause state */ - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) { - if (is_gmod_active(sdev) && is_smod_active(pc_node->qs) && is_qmod_active(&pc_node->qs->ac_q[i]) && !is_in_pause(sdev)) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "fcq_wake_all_queues vif %d peer_index %d ac %d\n", pc_node->vif, pc_node->peer_index, i); - netif_wake_subqueue(pc_node->dev, pc_node->qs->ac_q[i].head.netif_queue_id); - } else { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "fcq_wake_all_queues vif %d peer_index %d ac %d not woken up!\n", pc_node->vif, pc_node->peer_index, i); - } - } - } - spin_unlock_bh(&peers_cache_lock); -} - -void scsc_wifi_fcq_pause_queues(struct slsi_dev *sdev) -{ - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Pause queues\n"); - atomic_set(&sdev->in_pause_state, 1); - fcq_stop_all_queues(sdev); -} - -void scsc_wifi_fcq_unpause_queues(struct slsi_dev *sdev) -{ - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Unpause queues\n"); - atomic_set(&sdev->in_pause_state, 0); - fcq_wake_all_queues(sdev); -} - -#ifdef ENABLE_QCOD -/* Detects AC queues that have stopped and redistributes the qmod - * returns true if the redistribute succeed (qmod increases) - * returns false if qmod was not redistributed - */ -static bool fcq_redistribute_qmod_before_stopping(struct scsc_wifi_fcq_data_qset *qs) -{ - struct scsc_wifi_fcq_q_header *queue; - int i, j; - u32 *qmod_table; - u32 val; - - /* Only BE, so skip as nothing could be done */ - if (qs->ac_inuse == 1) - return false; - - /* Go through the list of possible candidates */ - for (i = 1; i < SLSI_NETIF_Q_PER_PEER; i++) { - queue = &qs->ac_q[i].head; - if (queue->can_be_distributed && - (ktime_compare(ktime_get(), ktime_add_ms(queue->empty_t, scsc_wifi_fcq_distribution_delay_ms)) > 0)) { - /* This queue could be redistributed */ - qs->ac_inuse &= ~(1 << i); - /* To prevent further reallocation */ - queue->can_be_distributed = false; - qmod_table = &ac_q_layout[qs->ac_inuse >> 1][0]; - for (j = 0; j < SLSI_NETIF_Q_PER_PEER; j++) { - queue = &qs->ac_q[j].head; - val = (atomic_read(&qs->smod) * qmod_table[SLSI_NETIF_Q_PER_PEER - 1 - j]) / 1000; - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Detected non-active ac queue (%d). Redistribute qmod[%d] %d qcod %d\n", i, j, val, atomic_read(&queue->qcod)); - atomic_set(&queue->qmod, val); - } - return true; - } - } - - return false; -} - -static void fcq_redistribute_qmod(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u8 peer_index, u8 vif) -{ - int i; - struct scsc_wifi_fcq_q_header *queue_redis; - u32 *qmod_table; - u32 val; - - qmod_table = &ac_q_layout[qs->ac_inuse >> 1][0]; - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) { - queue_redis = &qs->ac_q[i].head; - val = (atomic_read(&qs->smod) * qmod_table[SLSI_NETIF_Q_PER_PEER - 1 - i]) / 1000; - atomic_set(&queue_redis->qmod, val); -#ifdef CLOSE_IN_OVERSHOOT - if (val > 0) { - /* Stop queue that are overshooted because the new smod/qmod */ - if (atomic_read(&queue_redis->active) && (atomic_read(&queue_redis->qcod) >= (atomic_read(&queue_redis->qmod) - STOP_GUARD_QMOD))) { - netif_stop_subqueue(dev, queue_redis->netif_queue_id); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Closing overshoot queue for vif: %d peer: %d ac: %d qcod (%d) qmod (%d)\n", vif, peer_index, i, atomic_read(&queue_redis->qcod), atomic_read(&queue_redis->qmod)); - atomic_set(&queue_redis->active, 0); - } - } -#endif - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Redistribute new value %d: qmod[%d] %d qcod %d active %d\n", val, i, atomic_read(&queue_redis->qmod), atomic_read(&queue_redis->qcod), atomic_read(&queue_redis->active)); - } -} -#endif - -static void fcq_redistribute_smod(struct net_device *dev, struct slsi_dev *sdev, int total_to_distribute) -{ -#ifdef CLOSE_IN_OVERSHOOT - int i; -#endif - u32 new_smod; -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - int get_total = 0; -#endif - struct peers_cache *pc_node, *next; - struct scsc_wifi_fcq_data_qset *qs_redis; - - /* Redistribute smod - qmod */ - /* Go through the list of nodes and redistribute smod and qmod accordingly */ - /* First, get the nominal smod and divide it by total of peers */ -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - get_total = total_to_distribute - total_in_sleep; - if (get_total > 0) - new_smod = scsc_wifi_fcq_smod / get_total; - /* Use the nominal total in case of failure */ - else - new_smod = scsc_wifi_fcq_smod / total; -#else - new_smod = scsc_wifi_fcq_smod / total_to_distribute; -#endif - /* Saturate if number is lower than certian low level */ - if (new_smod < scsc_wifi_fcq_minimum_smod) - new_smod = scsc_wifi_fcq_minimum_smod; - spin_lock_bh(&peers_cache_lock); - list_for_each_entry_safe(pc_node, next, &peers_cache_list, list) { - if (pc_node->is_unicast) { - qs_redis = pc_node->qs; -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - if (qs_redis->in_sleep) - atomic_set(&qs_redis->smod, 0); - else - atomic_set(&qs_redis->smod, new_smod); -#else - atomic_set(&qs_redis->smod, new_smod); -#endif -#ifdef CLOSE_IN_OVERSHOOT - /* Stop queues to avoid overshooting if scod > smod */ - if (is_smod_active(qs_redis) && atomic_read(&qs_redis->scod) >= (atomic_read(&qs_redis->smod) - STOP_GUARD_SMOD)) { - /* Disable the qs that is in overshoot */ - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) - netif_stop_subqueue(dev, qs_redis->ac_q[i].head.netif_queue_id); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Closing overshoot qs for vif %d peer_index %d\n", pc_node->vif, pc_node->peer_index); - atomic_set(&qs_redis->active, 0); - } -#endif -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Redistributed smod = %d for vif %d peer_index %d total %d total_in_sleep %d\n", new_smod, pc_node->vif, pc_node->peer_index, total_to_distribute, total_in_sleep); -#else - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Redistributed smod = %d for vif %d peer_index %d total %d\n", new_smod, pc_node->vif, pc_node->peer_index, total_to_distribute); -#endif - /* Redistribute the qmod */ - fcq_redistribute_qmod(pc_node->dev, pc_node->qs, sdev, pc_node->peer_index, pc_node->vif); - } - } - spin_unlock_bh(&peers_cache_lock); -} - -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION -static int fcq_redistribute_smod_before_stopping(struct net_device *dev, struct slsi_dev *sdev, int total_to_distribute) -{ - struct peers_cache *pc_node, *next; - - /* only one peer, skip */ - if (total_to_distribute == 1) - return false; - - /* Search for nodes that were empty and are candidates to be redistributed */ - spin_lock_bh(&peers_cache_lock); - list_for_each_entry_safe(pc_node, next, &peers_cache_list, list) { - if (pc_node->is_unicast) { - if (pc_node->qs->can_be_distributed && - (ktime_compare(ktime_get(), ktime_add_ms(pc_node->qs->empty_t, 5000)) > 0)) { - pc_node->qs->in_sleep = true; - total_in_sleep += 1; - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Smod qs empty. Can be redistributed for vif %d peer_index %d qs->can_be_distributed %d\n", pc_node->vif, pc_node->peer_index, pc_node->qs->can_be_distributed); - pc_node->qs->can_be_distributed = false; - spin_unlock_bh(&peers_cache_lock); - fcq_redistribute_smod(dev, sdev, total_to_distribute); - return true; - } - } - } - spin_unlock_bh(&peers_cache_lock); - return false; -} -#endif - -static int fcq_transmit_gmod_domain(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - int gcod; - int gmod; - - spin_lock(&sdev->hip4_inst.hip_priv->gbot_lock); - - /* Check first the global domain */ - if (sdev->hip4_inst.hip_priv->saturated) { -#ifdef CONFIG_SCSC_DEBUG - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx Global domain. No space. active: %d vif: %d peer: %d ac: %d gcod (%d) gmod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&sdev->hip4_inst.hip_priv->gactive), vif, peer_index, priority, atomic_read(&sdev->hip4_inst.hip_priv->gcod), atomic_read(&sdev->hip4_inst.hip_priv->gmod), - td[DIREC_TX][DOMAIN_G][0], td[DIREC_RX][DOMAIN_G][0], td[DIREC_TX][DOMAIN_G][2], td[DIREC_RX][DOMAIN_G][2], td[DIREC_TX][DOMAIN_G][3], td[DIREC_RX][DOMAIN_G][3]); - fcq_stop_all_queues(sdev); -#endif - spin_unlock(&sdev->hip4_inst.hip_priv->gbot_lock); - return -ENOSPC; - } - - if (!atomic_read(&sdev->hip4_inst.hip_priv->gactive) && sdev->hip4_inst.hip_priv->guard-- == 0) { -#ifdef CONFIG_SCSC_DEBUG - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx Global domain. Saturating Gmod. active: %d vif: %d peer: %d ac: %d gcod (%d) gmod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&sdev->hip4_inst.hip_priv->gactive), vif, peer_index, priority, atomic_read(&sdev->hip4_inst.hip_priv->gcod), atomic_read(&sdev->hip4_inst.hip_priv->gmod), - td[DIREC_TX][DOMAIN_G][0], td[DIREC_RX][DOMAIN_G][0], td[DIREC_TX][DOMAIN_G][2], td[DIREC_RX][DOMAIN_G][2], td[DIREC_TX][DOMAIN_G][3], td[DIREC_RX][DOMAIN_G][3]); -#endif - sdev->hip4_inst.hip_priv->saturated = true; - } - - gmod = atomic_read(&sdev->hip4_inst.hip_priv->gmod); - gcod = atomic_inc_return(&sdev->hip4_inst.hip_priv->gcod); -#ifdef CONFIG_SCSC_DEBUG - fcq_update_counters(DIREC_TX, DOMAIN_G, priority); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "tx: active: %d vif: %d peer: %d ac: %d gcod (%d) gmod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&sdev->hip4_inst.hip_priv->gactive), vif, peer_index, priority, gcod, gmod, - td[DIREC_TX][DOMAIN_G][0], td[DIREC_RX][DOMAIN_G][0], td[DIREC_TX][DOMAIN_G][2], td[DIREC_RX][DOMAIN_G][2], td[DIREC_TX][DOMAIN_G][3], td[DIREC_RX][DOMAIN_G][3]); -#endif - if (gcod >= (atomic_read(&sdev->hip4_inst.hip_priv->gmod) - STOP_GUARD_GMOD)) { - fcq_stop_all_queues(sdev); - if (atomic_read(&sdev->hip4_inst.hip_priv->gactive)) { - sdev->hip4_inst.hip_priv->guard = STOP_GUARD_GMOD; - /* if GUARD is zero, saturate inmmediatelly */ - if (sdev->hip4_inst.hip_priv->guard == 0) - sdev->hip4_inst.hip_priv->saturated = true; - } - atomic_set(&sdev->hip4_inst.hip_priv->gactive, 0); - SCSC_HIP4_SAMPLER_BOT_STOP_Q(sdev->minor_prof, peer_index << 2 | vif); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Global Queues Stopped. gcod (%d) >= gmod (%d) gactive(%d)\n", gcod, gmod, atomic_read(&sdev->hip4_inst.hip_priv->gactive)); - } - spin_unlock(&sdev->hip4_inst.hip_priv->gbot_lock); - - return 0; -} - -/* This function should be called in spinlock(qs) */ -static int fcq_transmit_smod_domain(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - int scod; - -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - if (qs->in_sleep) { - /* Queue was put in sleep and now has become active, need to redistribute smod */ - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Detected activity in sleep Qs active %d vif: %d peer: %d ac: %d\n", - atomic_read(&qs->active), vif, peer_index, priority); - /* Before redistributing need to update the redistribution parameters */ - qs->in_sleep = false; - if (total_in_sleep) - total_in_sleep -= 1; - fcq_redistribute_smod(dev, sdev, total); - } - /* If we transmit we consider the queue -not- empty */ - qs->can_be_distributed = false; -#endif - /* Check smod domain */ - if (qs->saturated) { - int i; - -#ifdef CONFIG_SCSC_DEBUG - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx Smod domain. No space. active %d vif: %d peer: %d ac: %d scod (%d) smod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&qs->active), vif, peer_index, priority, atomic_read(&qs->scod), atomic_read(&qs->smod), - td[DIREC_TX][DOMAIN_S][0], td[DIREC_RX][DOMAIN_S][0], td[DIREC_TX][DOMAIN_S][2], td[DIREC_RX][DOMAIN_S][2], td[DIREC_TX][DOMAIN_S][3], td[DIREC_RX][DOMAIN_S][3]); -#endif - - /* Close subqueues again */ - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) - netif_stop_subqueue(dev, qs->ac_q[i].head.netif_queue_id); - - return -ENOSPC; - } - /* Pass the frame until reaching the actual saturation */ - if (!atomic_read(&qs->active) && (qs->guard-- == 0)) { -#ifdef CONFIG_SCSC_DEBUG - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx Smod domain. Going into Saturation. active %d vif: %d peer: %d ac: %d scod (%d) smod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&qs->active), vif, peer_index, priority, atomic_read(&qs->scod), atomic_read(&qs->smod), - td[DIREC_TX][DOMAIN_S][0], td[DIREC_RX][DOMAIN_S][0], td[DIREC_TX][DOMAIN_S][2], td[DIREC_RX][DOMAIN_S][2], td[DIREC_TX][DOMAIN_S][3], td[DIREC_RX][DOMAIN_S][3]); -#endif - qs->saturated = true; - } - scod = atomic_inc_return(&qs->scod); - SCSC_HIP4_SAMPLER_BOT_TX(sdev->minor_prof, scod, atomic_read(&qs->smod), priority << 6 | (peer_index & 0xf) << 2 | vif); -#ifdef CONFIG_SCSC_DEBUG - fcq_update_counters(DIREC_TX, DOMAIN_S, priority); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "tx: active: %d vif: %d peer: %d ac: %d scod (%d) smod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&qs->active), vif, peer_index, priority, atomic_read(&qs->scod), atomic_read(&qs->smod), - td[DIREC_TX][DOMAIN_S][0], td[DIREC_RX][DOMAIN_S][0], td[DIREC_TX][DOMAIN_S][2], td[DIREC_RX][DOMAIN_S][2], td[DIREC_TX][DOMAIN_S][3], td[DIREC_RX][DOMAIN_S][3]); -#endif - if (scod >= (atomic_read(&qs->smod) - STOP_GUARD_SMOD)) { - int i; -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - /* Before closing check whether we could get slots from non used queues */ - if (fcq_redistribute_smod_before_stopping(dev, sdev, total)) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Skipped Stop vif: %d peer: %d. scod (%d) >= smod (%d)\n", vif, peer_index, atomic_read(&qs->scod), atomic_read(&qs->smod)); - return 0; - } -#endif - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) - netif_stop_subqueue(dev, qs->ac_q[i].head.netif_queue_id); - - if (atomic_read(&qs->active)) { - qs->guard = STOP_GUARD_SMOD; - /* if GUARD is zero, saturate inmmediatelly */ - if (qs->guard == 0) - qs->saturated = true; - } - atomic_set(&qs->active, 0); - qs->stats.netq_stops++; - SCSC_HIP4_SAMPLER_BOT_STOP_Q(sdev->minor_prof, peer_index << 2 | vif); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Smod Queues Stopped vif: %d peer: %d. scod (%d) >= smod (%d)\n", vif, peer_index, atomic_read(&qs->scod), atomic_read(&qs->smod)); - } - return 0; -} - -#if defined(ENABLE_CTRL_FCQ) || defined(ENABLE_QCOD) -/* This function should be called in spinlock(qs) */ -static int fcq_transmit_qmod_domain(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u16 priority, u8 peer_index, u8 vif) -{ - struct scsc_wifi_fcq_q_header *queue; - int qcod; - - queue = &qs->ac_q[priority].head; - - if (!(qs->ac_inuse & (1 << priority))) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "New AC detected: %d\n", priority); - qs->ac_inuse |= (1 << priority); - fcq_redistribute_qmod(dev, qs, sdev, peer_index, vif); - queue->can_be_distributed = false; - } - - if (queue->saturated) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx No space in ac: %d\n", priority); - /* Stop subqueue */ - netif_stop_subqueue(dev, queue->netif_queue_id); - return -ENOSPC; - } - - /* Pass the frame until reaching the actual saturation */ - if (!atomic_read(&queue->active) && (queue->guard-- == 0)) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx No space in ac: %d Saturated\n", priority); - queue->saturated = true; - } - - qcod = atomic_inc_return(&queue->qcod); - SCSC_HIP4_SAMPLER_BOT_QMOD_TX(sdev->minor_prof, qcod, atomic_read(&queue->qmod), priority << 6 | (peer_index & 0xf) << 2 | vif); -#ifdef CONFIG_SCSC_DEBUG - fcq_update_counters(DIREC_TX, DOMAIN_Q, priority); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "tx: active: %d vif: %d peer: %d ac: %d qcod (%d) qmod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&queue->active), vif, peer_index, priority, atomic_read(&queue->qcod), atomic_read(&queue->qmod), - td[DIREC_TX][DOMAIN_Q][0], td[DIREC_RX][DOMAIN_Q][0], td[DIREC_TX][DOMAIN_Q][2], td[DIREC_RX][DOMAIN_Q][2], td[DIREC_TX][DOMAIN_Q][3], td[DIREC_RX][DOMAIN_Q][3]); -#endif - if (atomic_read(&queue->active) && qcod >= (atomic_read(&queue->qmod) - STOP_GUARD_QMOD)) { - /* Before closing check whether we could get slots from non used queues */ -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - if (fcq_redistribute_smod_before_stopping(dev, sdev, total)) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Skipped Stop vif: %d peer: %d. scod (%d) >= smod (%d)\n", vif, peer_index, atomic_read(&qs->scod), atomic_read(&qs->smod)); - goto skip_stop; - } -#endif - if (fcq_redistribute_qmod_before_stopping(qs)) - goto skip_stop; - SCSC_HIP4_SAMPLER_BOT_QMOD_STOP(sdev->minor_prof, priority << 6 | (peer_index & 0xf) << 2 | vif); - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "Stop subqueue vif: %d peer: %d ac: %d qcod (%d) qmod (%d)\n", vif, peer_index, priority, atomic_read(&queue->qcod), atomic_read(&queue->qmod)); - if (atomic_read(&queue->active)) { - queue->guard = STOP_GUARD_QMOD; - /* if GUARD is zero, saturate inmmediatelly */ - if (queue->guard == 0) - queue->saturated = true; - } - atomic_set(&queue->active, 0); - netif_stop_subqueue(dev, queue->netif_queue_id); - queue->stats.netq_stops++; - } -skip_stop: - return 0; -} -#endif - -int scsc_wifi_fcq_transmit_ctrl(struct net_device *dev, struct scsc_wifi_fcq_ctrl_q *queue) -{ - int rc = 0; - -#ifdef ENABLE_CTRL_FCQ - if (WARN_ON(!dev)) - return -EINVAL; - - if (WARN_ON(!queue)) - return -EINVAL; - - rc = fcq_transmit_qmod_domain(dev, &queue->head); -#endif - return rc; -} - -int scsc_wifi_fcq_transmit_data(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - int rc; - struct peers_cache *pc_node, *next; - - if (WARN_ON(!dev)) - return -EINVAL; - - if (WARN_ON(!qs)) - return -EINVAL; - - if (WARN_ON(priority >= ARRAY_SIZE(qs->ac_q))) - return -EINVAL; - - spin_lock_bh(&qs->cp_lock); - /* Check caller matches an existing peer record */ - spin_lock_bh(&peers_cache_lock); - list_for_each_entry_safe(pc_node, next, &peers_cache_list, list) { - if (pc_node->qs == qs && pc_node->peer_index == peer_index && - pc_node->vif == vif && pc_node->dev == dev) { - spin_unlock_bh(&peers_cache_lock); - goto found; - } - } - spin_unlock_bh(&peers_cache_lock); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Packet dropped. Detected incorrect peer record\n"); - spin_unlock_bh(&qs->cp_lock); - return -EINVAL; -found: - /* Controlled port is not yet open; so can't send data frame */ - if (qs->controlled_port_state == SCSC_WIFI_FCQ_8021x_STATE_BLOCKED) { - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "8021x_STATE_BLOCKED\n"); - spin_unlock_bh(&qs->cp_lock); - return -EPERM; - } - rc = fcq_transmit_gmod_domain(dev, qs, priority, sdev, vif, peer_index); - if (rc) { - spin_unlock_bh(&qs->cp_lock); - return rc; - } - - rc = fcq_transmit_smod_domain(dev, qs, priority, sdev, vif, peer_index); - if (rc) { - /* Queue is full and was not active, so decrement gcod since - * this packet won't be transmitted, but the overall gcod - * resource is still available. This situation should never - * happen if flow control works as expected. - */ - atomic_dec(&sdev->hip4_inst.hip_priv->gcod); - spin_unlock_bh(&qs->cp_lock); - return rc; - } - -#ifdef ENABLE_QCOD - rc = fcq_transmit_qmod_domain(dev, qs, sdev, priority, peer_index, vif); - if (rc) { - /* Queue is full and was not active, so decrement scod since - * this packet won't be transmitted, but the overall scod - * resource is still available. This situation should never - * happen if flow control works as expected. - */ - atomic_dec(&qs->scod); - atomic_dec(&sdev->hip4_inst.hip_priv->gcod); - spin_unlock_bh(&qs->cp_lock); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx scsc_wifi_fcq_transmit_data: Flow control not respected. Packet will be dropped.\n"); - return rc; - } -#endif - - spin_unlock_bh(&qs->cp_lock); - return 0; -} - -static int fcq_receive_gmod_domain(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u16 priority, u8 peer_index, u8 vif) -{ - int gcod; - int gmod; - int gactive; - - spin_lock(&sdev->hip4_inst.hip_priv->gbot_lock); - /* Decrease first the global domain */ - gmod = atomic_read(&sdev->hip4_inst.hip_priv->gmod); - gcod = atomic_dec_return(&sdev->hip4_inst.hip_priv->gcod); - gactive = atomic_read(&sdev->hip4_inst.hip_priv->gactive); - if (unlikely(gcod < 0)) { - atomic_set(&sdev->hip4_inst.hip_priv->gcod, 0); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx scsc_wifi_fcq_receive: gcod is negative. Has been fixed\n"); - } - -#ifdef CONFIG_SCSC_DEBUG - fcq_update_counters(DIREC_RX, DOMAIN_G, priority); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "rx: active: %d vif: %d peer: %d ac: %d gcod (%d) gmod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d %s\n", - gactive, vif, peer_index, priority, gcod, gmod, - td[DIREC_TX][DOMAIN_G][0], td[DIREC_RX][DOMAIN_G][0], td[DIREC_TX][DOMAIN_G][2], td[DIREC_RX][DOMAIN_G][2], td[DIREC_TX][DOMAIN_G][3], td[DIREC_RX][DOMAIN_G][3], qs ? "" : "NO PEER"); -#endif - - if (!is_gmod_active(sdev) && (gcod + SCSC_WIFI_FCQ_GMOD_RESUME_HYSTERESIS / total < gmod)) { - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Global Queues Started. gcod (%d) < gmod (%d)\n", gcod, gmod); - sdev->hip4_inst.hip_priv->saturated = false; - atomic_set(&sdev->hip4_inst.hip_priv->gactive, 1); - fcq_wake_all_queues(sdev); - } - spin_unlock(&sdev->hip4_inst.hip_priv->gbot_lock); - - return 0; -} - -static int fcq_receive_smod_domain(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u16 priority, u8 peer_index, u8 vif) -{ - int scod; - - scod = atomic_dec_return(&qs->scod); - if (unlikely(scod < 0)) { - atomic_set(&qs->scod, 0); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx scsc_wifi_fcq_receive: scod is negative. Has been fixed\n"); - } - -#ifdef CONFIG_SCSC_DEBUG - fcq_update_counters(DIREC_RX, DOMAIN_S, priority); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "rx: active: %d vif: %d peer: %d ac: %d scod (%d) smod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&qs->active), vif, peer_index, priority, atomic_read(&qs->scod), atomic_read(&qs->smod), - td[DIREC_TX][DOMAIN_S][0], td[DIREC_RX][DOMAIN_S][0], td[DIREC_TX][DOMAIN_S][2], td[DIREC_RX][DOMAIN_S][2], td[DIREC_TX][DOMAIN_S][3], td[DIREC_RX][DOMAIN_S][3]); -#endif - /* Only support a maximum of 16 peers!!!!!!*/ - SCSC_HIP4_SAMPLER_BOT_RX(sdev->minor_prof, scod, atomic_read(&qs->smod), priority << 6 | (peer_index & 0xf) << 2 | vif); - if (!is_smod_active(qs) && (scod + SCSC_WIFI_FCQ_SMOD_RESUME_HYSTERESIS / total < atomic_read(&qs->smod))) { - int i; - /* Resume all queues for this peer that were active . Do not wake queues in pause state or closed in upper domains */ - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) { - if (is_gmod_active(sdev) && is_qmod_active(&qs->ac_q[i]) && !is_in_pause(sdev)) - netif_wake_subqueue(dev, qs->ac_q[i].head.netif_queue_id); - else - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "smod wake vif %d peer_index %d ac %d not woken up!\n", vif, peer_index, i); - } - - SCSC_HIP4_SAMPLER_BOT_START_Q(sdev->minor_prof, peer_index << 2 | vif); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Smod Queues Started vif: %d peer: %d. scod (%d) >= smod (%d)\n", vif, peer_index, atomic_read(&qs->scod), atomic_read(&qs->smod)); - /* Regardless the queue were not woken up, set the qs as active */ - qs->saturated = false; - atomic_set(&qs->active, 1); - qs->stats.netq_resumes++; - } - -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - if (scod == 0) { - /* Get the empty time */ - qs->empty_t = ktime_get(); - qs->can_be_distributed = true; - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Qs empty vif: %d peer: %d\n", vif, peer_index); - } else { - qs->can_be_distributed = false; - } -#endif - return 0; -} - -#ifdef ENABLE_QCOD -static int fcq_receive_qmod_domain(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u16 priority, u8 peer_index, u8 vif) -{ - struct scsc_wifi_fcq_q_header *queue; - int qcod; - - queue = &qs->ac_q[priority].head; - - qcod = atomic_dec_return(&queue->qcod); - if (unlikely(qcod < 0)) { - atomic_set(&queue->qcod, 0); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "xxxxxxxxxxxxxxxxxxxxxxx fcq_receive_qmod_domain: qcod is negative. Has been fixed\n"); - } - -#ifdef CONFIG_SCSC_DEBUG - fcq_update_counters(DIREC_RX, DOMAIN_Q, priority); - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "rx: active: %d vif: %d peer: %d ac: %d qcod (%d) qmod (%d) betx:%d berx:%d vitx:%d virx:%d votx:%d vorx:%d\n", - atomic_read(&queue->active), vif, peer_index, priority, atomic_read(&queue->qcod), atomic_read(&queue->qmod), - td[DIREC_TX][DOMAIN_Q][0], td[DIREC_RX][DOMAIN_Q][0], td[DIREC_TX][DOMAIN_Q][2], td[DIREC_RX][DOMAIN_Q][2], td[DIREC_TX][DOMAIN_Q][3], td[DIREC_RX][DOMAIN_Q][3]); -#endif - SCSC_HIP4_SAMPLER_BOT_QMOD_RX(sdev->minor_prof, qcod, atomic_read(&queue->qmod), priority << 6 | (peer_index & 0xf) << 2 | vif); - - if (!is_qmod_active(&qs->ac_q[priority]) && ((qcod + SCSC_WIFI_FCQ_QMOD_RESUME_HYSTERESIS / total) < atomic_read(&queue->qmod))) { - /* Do not wake queues in pause state or closed by other domain */ - if (is_gmod_active(sdev) && is_smod_active(qs) && !is_in_pause(sdev)) - netif_wake_subqueue(dev, queue->netif_queue_id); - /* Only support a maximum of 16 peers!!!!!!*/ - SCSC_HIP4_SAMPLER_BOT_QMOD_START(sdev->minor_prof, priority << 6 | (peer_index & 0xf) << 2 | vif); - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "Start subqueue vif: %d peer: %d ac: %d qcod (%d) qmod (%d)\n", vif, peer_index, priority, atomic_read(&queue->qcod), atomic_read(&queue->qmod)); - queue->stats.netq_resumes++; - /* Regardless the queue was not woken up, set the queue as active */ - queue->saturated = false; - atomic_set(&queue->active, 1); - } - - /* Ignore priority BE as it it always active */ - if (qcod == 0 && priority != SLSI_TRAFFIC_Q_BE) { - /* Get the stop time */ - queue->empty_t = ktime_get(); - queue->can_be_distributed = true; - } else { - queue->can_be_distributed = false; - } - return 0; -} -#endif - -int scsc_wifi_fcq_receive_ctrl(struct net_device *dev, struct scsc_wifi_fcq_ctrl_q *queue) -{ - if (WARN_ON(!dev)) - return -EINVAL; - - if (WARN_ON(!queue)) - return -EINVAL; - -#ifdef ENABLE_CTRL_FCQ - /* return fcq_receive(dev, &queue->head, NULL, 0, 0, 0); */ -#endif - return 0; -} - -/* This function is to collect missing returning mbulks from a peer that has dissapeared so the qset is missing */ -int scsc_wifi_fcq_receive_data_no_peer(struct net_device *dev, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - fcq_receive_gmod_domain(dev, NULL, sdev, priority, peer_index, vif); -#ifdef CONFIG_SCSC_DEBUG - /* Update also S and Q domain */ - fcq_update_counters(DIREC_RX, DOMAIN_S, priority); - fcq_update_counters(DIREC_RX, DOMAIN_Q, priority); -#endif - return 0; -} - -int scsc_wifi_fcq_receive_data(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - int rc = 0; - - if (WARN_ON(!dev)) - return -EINVAL; - - if (WARN_ON(!qs)) - return -EINVAL; - - if (WARN_ON(priority >= ARRAY_SIZE(qs->ac_q))) - return -EINVAL; - - /* The read/modify/write of the scod here needs synchronisation. */ - spin_lock_bh(&qs->cp_lock); - - rc = fcq_receive_gmod_domain(dev, qs, sdev, priority, peer_index, vif); - if (rc) - goto end; - - rc = fcq_receive_smod_domain(dev, qs, sdev, priority, peer_index, vif); - if (rc) - goto end; - -#ifdef ENABLE_QCOD - rc = fcq_receive_qmod_domain(dev, qs, sdev, priority, peer_index, vif); -#endif -end: - spin_unlock_bh(&qs->cp_lock); - return rc; -} - -int scsc_wifi_fcq_update_smod(struct scsc_wifi_fcq_data_qset *qs, enum scsc_wifi_fcq_ps_state peer_ps_state, - enum scsc_wifi_fcq_queue_set_type type) -{ - if (WARN_ON(!qs)) - return -EINVAL; - - if (peer_ps_state == SCSC_WIFI_FCQ_PS_STATE_POWERSAVE) { - atomic_set(&qs->smod, type == SCSC_WIFI_FCQ_QUEUE_SET_TYPE_UNICAST ? scsc_wifi_fcq_smod_power : scsc_wifi_fcq_mcast_smod_power); - qs->peer_ps_state = peer_ps_state; - qs->peer_ps_state_transitions++; - } else if (peer_ps_state == SCSC_WIFI_FCQ_PS_STATE_ACTIVE) { - atomic_set(&qs->smod, type == SCSC_WIFI_FCQ_QUEUE_SET_TYPE_UNICAST ? scsc_wifi_fcq_smod : scsc_wifi_fcq_mcast_smod); - qs->peer_ps_state = peer_ps_state; - qs->peer_ps_state_transitions++; - } else - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Unknown sta_state %d\n", - peer_ps_state); - - return 0; -} - -int scsc_wifi_fcq_8021x_port_state(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, enum scsc_wifi_fcq_8021x_state state) -{ - if (WARN_ON(!dev)) - return -EINTR; - - if (WARN_ON(!qs)) - return -EINVAL; - - spin_lock_bh(&qs->cp_lock); - qs->controlled_port_state = state; - spin_unlock_bh(&qs->cp_lock); - SLSI_NET_DBG1(dev, SLSI_WIFI_FCQ, "802.1x: Queue set 0x%p is %s\n", qs, - state == SCSC_WIFI_FCQ_8021x_STATE_OPEN ? "Open" : "Blocked"); - return 0; -} - -/** - * Statistics - */ -int scsc_wifi_fcq_stat_queue(struct scsc_wifi_fcq_q_header *queue, - struct scsc_wifi_fcq_q_stat *queue_stat, - int *qmod, int *qcod) -{ - if (WARN_ON(!queue) || WARN_ON(!queue_stat) || WARN_ON(!qmod) || WARN_ON(!qmod)) - return -EINTR; - - memcpy(queue_stat, &queue->stats, sizeof(struct scsc_wifi_fcq_q_stat)); - *qmod = atomic_read(&queue->qmod); - *qcod = atomic_read(&queue->qcod); - return 0; -} - -int scsc_wifi_fcq_stat_queueset(struct scsc_wifi_fcq_data_qset *queue_set, - struct scsc_wifi_fcq_q_stat *queue_stat, - int *smod, int *scod, enum scsc_wifi_fcq_8021x_state *cp_state, - u32 *peer_ps_state_transitions) -{ - if (WARN_ON(!queue_set) || WARN_ON(!queue_stat) || WARN_ON(!smod) || WARN_ON(!scod) || - WARN_ON(!cp_state) || WARN_ON(!peer_ps_state_transitions)) - return -EINTR; - - memcpy(queue_stat, &queue_set->stats, sizeof(struct scsc_wifi_fcq_q_stat)); - *peer_ps_state_transitions = queue_set->peer_ps_state_transitions; - *cp_state = queue_set->controlled_port_state; - *smod = atomic_read(&queue_set->smod); - *scod = atomic_read(&queue_set->scod); - return 0; -} - -/** - * Queue and Queue Set init/deinit - */ -int scsc_wifi_fcq_ctrl_q_init(struct scsc_wifi_fcq_ctrl_q *queue) -{ - if (WARN_ON(!queue)) - return -EINVAL; - - /* Ensure that default qmod doesn't exceed 24 bit */ - if (WARN_ON(scsc_wifi_fcq_qmod >= 0x1000000)) - return -EINVAL; - - atomic_set(&queue->head.qmod, scsc_wifi_fcq_qmod); - atomic_set(&queue->head.qcod, 0); - queue->head.netif_queue_id = 0; - queue->head.stats.netq_stops = 0; - queue->head.stats.netq_resumes = 0; - atomic_set(&queue->head.active, 1); - - return 0; -} - -void scsc_wifi_fcq_ctrl_q_deinit(struct scsc_wifi_fcq_ctrl_q *queue) -{ - int qcod; - - WARN_ON(!queue); - - qcod = atomic_read(&queue->head.qcod); - if (qcod != 0) - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Ctrl queue (0x%p) deinit: qcod is %d, netif queue %d\n", - queue, qcod, queue->head.netif_queue_id); -} - -static int fcq_data_q_init(struct net_device *dev, struct slsi_dev *sdev, enum scsc_wifi_fcq_queue_set_type type, struct scsc_wifi_fcq_data_q *queue, - struct scsc_wifi_fcq_data_qset *qs, u8 qs_num, s16 ac) -{ - if (WARN_ON(!queue)) - return -EINVAL; - - if (WARN_ON(!qs)) - return -EINVAL; - - /* Ensure that default qmods don't exceed 24 bit */ - if (WARN_ON(scsc_wifi_fcq_qmod >= 0x1000000) || WARN_ON(scsc_wifi_fcq_mcast_qmod >= 0x1000000)) - return -EINVAL; - - atomic_set(&queue->head.qmod, type == SCSC_WIFI_FCQ_QUEUE_SET_TYPE_UNICAST ? scsc_wifi_fcq_qmod : scsc_wifi_fcq_mcast_qmod); - - atomic_set(&queue->head.qcod, 0); - queue->qs = qs; - queue->head.netif_queue_id = type == SCSC_WIFI_FCQ_QUEUE_SET_TYPE_UNICAST ? - slsi_netif_get_peer_queue(qs_num, ac) : slsi_netif_get_multicast_queue(ac); - - queue->head.stats.netq_stops = 0; - queue->head.stats.netq_resumes = 0; - - /* TODO: This could generate some ENOSPC if queues are full */ - if (!atomic_read(&sdev->in_pause_state)) - netif_wake_subqueue(dev, queue->head.netif_queue_id); - - queue->head.saturated = false; - atomic_set(&queue->head.active, 1); - - return 0; -} - -static void fcq_data_q_deinit(struct scsc_wifi_fcq_data_q *queue) -{ - int qcod; - - WARN_ON(!queue); - - qcod = atomic_read(&queue->head.qcod); - if (qcod != 0) - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Data queue (0x%p) deinit: qcod is %d, netif queue %d\n", - queue, qcod, queue->head.netif_queue_id); -} - -static void fcq_qset_init(struct net_device *dev, struct slsi_dev *sdev, enum scsc_wifi_fcq_queue_set_type type, struct scsc_wifi_fcq_data_qset *qs, u8 qs_num) -{ - int i; - struct scsc_wifi_fcq_data_q *queue; - - memset(qs, 0, sizeof(struct scsc_wifi_fcq_data_qset)); - spin_lock_init(&qs->cp_lock); - atomic_set(&qs->smod, type == SCSC_WIFI_FCQ_QUEUE_SET_TYPE_UNICAST ? scsc_wifi_fcq_smod : scsc_wifi_fcq_mcast_smod); - atomic_set(&qs->scod, 0); - - spin_lock_bh(&qs->cp_lock); - qs->peer_ps_state = SCSC_WIFI_FCQ_PS_STATE_ACTIVE; - qs->saturated = false; - atomic_set(&qs->active, 1); -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - qs->in_sleep = false; - qs->can_be_distributed = false; -#endif - qs->controlled_port_state = SCSC_WIFI_FCQ_8021x_STATE_BLOCKED; - - /* Queues init */ - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) { - /* Clear all the bits */ - qs->ac_inuse &= ~(1 << i); - queue = &qs->ac_q[i]; - fcq_data_q_init(dev, sdev, type, queue, qs, qs_num, i); - } - /* Give all qmod to BE */ - qs->ac_inuse = 1; - spin_unlock_bh(&qs->cp_lock); -} - -int scsc_wifi_fcq_unicast_qset_init(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u8 qs_num, struct slsi_dev *sdev, u8 vif, struct slsi_peer *peer) -{ - struct peers_cache *pc_new_node; - - if (WARN_ON(!qs)) - return -EINVAL; - - /* Ensure that default smod doesn't exceed 24 bit */ - if (WARN_ON(scsc_wifi_fcq_smod >= 0x1000000)) - return -EINVAL; - - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Init unicast queue set 0x%p vif %d peer_index %d\n", qs, vif, peer->aid); - fcq_qset_init(dev, sdev, SCSC_WIFI_FCQ_QUEUE_SET_TYPE_UNICAST, qs, qs_num); - SCSC_HIP4_SAMPLER_BOT_ADD(sdev->minor_prof, peer->address[4], peer->address[5], peer->aid << 2 | vif); - SCSC_HIP4_SAMPLER_BOT_TX(sdev->minor_prof, atomic_read(&qs->scod), atomic_read(&qs->smod), peer->aid << 2 | vif); - /* Cache the added peer to optimize the Global start/stop process */ - pc_new_node = kzalloc(sizeof(*pc_new_node), GFP_ATOMIC); - if (!pc_new_node) - return -ENOMEM; - pc_new_node->dev = dev; - pc_new_node->qs = qs; - pc_new_node->peer_index = peer->aid; - pc_new_node->vif = vif; - pc_new_node->is_unicast = true; - - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "Add new peer qs %p vif %d peer->aid %d\n", qs, vif, peer->aid); - spin_lock_bh(&peers_cache_lock); - list_add_tail(&pc_new_node->list, &peers_cache_list); - spin_unlock_bh(&peers_cache_lock); - - if (total == 0) { - /* No peers. Reset gcod. */ -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - total_in_sleep = 0; -#endif - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "First peer. Reset gcod.\n"); - atomic_set(&sdev->hip4_inst.hip_priv->gcod, 0); - atomic_set(&sdev->hip4_inst.hip_priv->gactive, 1); - sdev->hip4_inst.hip_priv->saturated = false; - } - - total++; - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Add New peer. Total %d\n", total); - fcq_redistribute_smod(dev, sdev, total); - - return 0; -} - -int scsc_wifi_fcq_multicast_qset_init(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u8 vif) -{ - struct peers_cache *pc_node; - - if (WARN_ON(!qs)) - return -EINVAL; - - /* Ensure that default smod doesn't exceed 24 bit */ - if (WARN_ON(scsc_wifi_fcq_mcast_smod >= 0x1000000)) - return -EINVAL; - - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Init multicast queue set 0x%p\n", qs); - fcq_qset_init(dev, sdev, SCSC_WIFI_FCQ_QUEUE_SET_TYPE_MULTICAST, qs, 0); - SCSC_HIP4_SAMPLER_BOT_ADD(sdev->minor_prof, 0, 0, vif); - SCSC_HIP4_SAMPLER_BOT_TX(sdev->minor_prof, atomic_read(&qs->scod), atomic_read(&qs->smod), vif); - - /* Cache the added peer to optimize the Global start/stop process */ - pc_node = kzalloc(sizeof(*pc_node), GFP_ATOMIC); - if (!pc_node) - return -ENOMEM; - pc_node->dev = dev; - pc_node->qs = qs; - pc_node->peer_index = 0; - pc_node->vif = vif; - pc_node->is_unicast = false; - - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "Add Multicast Qset %p vif %d peer->aid 0\n", qs, vif); - spin_lock_bh(&peers_cache_lock); - list_add_tail(&pc_node->list, &peers_cache_list); - spin_unlock_bh(&peers_cache_lock); - - fcq_redistribute_qmod(pc_node->dev, pc_node->qs, sdev, pc_node->peer_index, pc_node->vif); - - return 0; -} - -void scsc_wifi_fcq_qset_deinit(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u8 vif, struct slsi_peer *peer) -{ - struct peers_cache *pc_node, *next; - int i, scod; -#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING - int aid = 0; - u8 addr_4 = 0; - u8 addr_5 = 0; - - if (peer) { - aid = peer->aid; - addr_4 = peer->address[4]; - addr_5 = peer->address[5]; - } -#endif - - WARN_ON(!qs); - - if (!qs) - return; - - scod = atomic_read(&qs->scod); - if (scod != 0) - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "Data set (0x%p) deinit: scod is %d\n", qs, scod); - - for (i = 0; i < SLSI_NETIF_Q_PER_PEER; i++) - fcq_data_q_deinit(&qs->ac_q[i]); - - qs->ac_inuse = 0; -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - /* Remove from total sleep if was in sleep */ - if (qs->in_sleep && total_in_sleep) - total_in_sleep -= 1; -#endif - SCSC_HIP4_SAMPLER_BOT_RX(sdev->minor_prof, 0, 0, (aid & 0xf) << 2 | vif); - SCSC_HIP4_SAMPLER_BOT_REMOVE(sdev->minor_prof, addr_4, addr_5, aid << 2 | vif); - - if (peer) - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "Delete qs %p vif %d peer->aid %d\n", qs, vif, peer->aid); - else - SLSI_DBG1_NODEV(SLSI_WIFI_FCQ, "Delete qs %p vif %d Multicast\n", qs, vif); - - spin_lock_bh(&peers_cache_lock); - list_for_each_entry_safe(pc_node, next, &peers_cache_list, list) { - if (pc_node->qs == qs) { - list_del(&pc_node->list); - kfree(pc_node); - } - } - spin_unlock_bh(&peers_cache_lock); - /* Only count unicast qs */ - if (total > 0 && peer) - total--; - - SLSI_DBG4_NODEV(SLSI_WIFI_FCQ, "Del peer. Total %d\n", total); - - if (total == 0) - return; - - fcq_redistribute_smod(dev, sdev, total); -} diff --git a/drivers/net/wireless/scsc/scsc_wifi_fcq.h b/drivers/net/wireless/scsc/scsc_wifi_fcq.h deleted file mode 100644 index 9d82c158c4f4..000000000000 --- a/drivers/net/wireless/scsc/scsc_wifi_fcq.h +++ /dev/null @@ -1,115 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include -#include -#include "netif.h" - -#ifndef __SCSC_WIFI_FCQ_H -#define __SCSC_WIFI_FCQ_H - -enum scsc_wifi_fcq_8021x_state { - SCSC_WIFI_FCQ_8021x_STATE_BLOCKED = 0, - SCSC_WIFI_FCQ_8021x_STATE_OPEN = 1 -}; - -enum scsc_wifi_fcq_ps_state { - SCSC_WIFI_FCQ_PS_STATE_POWERSAVE = 1, - SCSC_WIFI_FCQ_PS_STATE_ACTIVE = 2 -}; - -struct scsc_wifi_fcq_q_stat { - u32 netq_stops; - u32 netq_resumes; -}; - -struct scsc_wifi_fcq_q_header { - atomic_t qmod; - atomic_t qcod; - u16 netif_queue_id; - atomic_t active; - struct scsc_wifi_fcq_q_stat stats; - ktime_t empty_t; - bool can_be_distributed; - bool saturated; - int guard; -}; - -struct scsc_wifi_fcq_data_q { - struct scsc_wifi_fcq_q_header head; - struct scsc_wifi_fcq_data_qset *qs; -}; - -struct scsc_wifi_fcq_ctrl_q { - struct scsc_wifi_fcq_q_header head; -}; - -enum scsc_wifi_fcq_queue_set_type { - SCSC_WIFI_FCQ_QUEUE_SET_TYPE_UNICAST = 0, - SCSC_WIFI_FCQ_QUEUE_SET_TYPE_MULTICAST = 1 -}; - -#define EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION 1 - -struct scsc_wifi_fcq_data_qset { - atomic_t active; - enum scsc_wifi_fcq_8021x_state controlled_port_state; - /* a std spinlock */ - spinlock_t cp_lock; - - struct scsc_wifi_fcq_data_q ac_q[SLSI_NETIF_Q_PER_PEER]; - /* Control AC usage (BE,BK,VI,VO) bitmap*/ - u8 ac_inuse; - atomic_t smod; - atomic_t scod; - - struct scsc_wifi_fcq_q_stat stats; /* Stats for smod */ - enum scsc_wifi_fcq_ps_state peer_ps_state; - u32 peer_ps_state_transitions; - -#ifdef EXPERIMENTAL_DYNAMIC_SMOD_ADAPTATION - ktime_t empty_t; - bool can_be_distributed; - bool in_sleep; -#endif - bool saturated; - int guard; -}; - -/* Queue and queue set management */ -int scsc_wifi_fcq_ctrl_q_init(struct scsc_wifi_fcq_ctrl_q *queue); -void scsc_wifi_fcq_ctrl_q_deinit(struct scsc_wifi_fcq_ctrl_q *queue); - -int scsc_wifi_fcq_unicast_qset_init(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u8 qs_num, struct slsi_dev *sdev, u8 vif, struct slsi_peer *peer); -int scsc_wifi_fcq_multicast_qset_init(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u8 vif); -void scsc_wifi_fcq_qset_deinit(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u8 vif, struct slsi_peer *peer); - -/* Transmit/receive bookkeeping and smod power save changes / 802.1x handling */ -int scsc_wifi_fcq_transmit_data(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index); -int scsc_wifi_fcq_receive_data(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index); -int scsc_wifi_fcq_receive_data_no_peer(struct net_device *dev, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index); - -void scsc_wifi_fcq_pause_queues(struct slsi_dev *sdev); -void scsc_wifi_fcq_unpause_queues(struct slsi_dev *sdev); - -int scsc_wifi_fcq_transmit_ctrl(struct net_device *dev, struct scsc_wifi_fcq_ctrl_q *queue); -int scsc_wifi_fcq_receive_ctrl(struct net_device *dev, struct scsc_wifi_fcq_ctrl_q *queue); - -int scsc_wifi_fcq_update_smod(struct scsc_wifi_fcq_data_qset *qs, enum scsc_wifi_fcq_ps_state peer_ps_state, - enum scsc_wifi_fcq_queue_set_type type); -int scsc_wifi_fcq_8021x_port_state(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, enum scsc_wifi_fcq_8021x_state state); - -/* Statistics */ -int scsc_wifi_fcq_stat_queue(struct scsc_wifi_fcq_q_header *queue, - struct scsc_wifi_fcq_q_stat *queue_stat, - int *qmod, int *qcod); - -int scsc_wifi_fcq_stat_queueset(struct scsc_wifi_fcq_data_qset *queue_set, - struct scsc_wifi_fcq_q_stat *queue_stat, - int *smod, int *scod, enum scsc_wifi_fcq_8021x_state *cp_state, - u32 *peer_ps_state_transitions); - -#endif /* #ifndef __SCSC_WIFI_FCQ_H */ diff --git a/drivers/net/wireless/scsc/src_sink.c b/drivers/net/wireless/scsc/src_sink.c deleted file mode 100755 index 24b16179e536..000000000000 --- a/drivers/net/wireless/scsc/src_sink.c +++ /dev/null @@ -1,417 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "dev.h" /* sdev access */ -#include "src_sink.h" -#include "debug.h" -#include "fapi.h" -#include "mlme.h" -#include "mgt.h" - -static int slsi_src_sink_fake_sta_start(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - u8 device_address[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - u8 fake_peer_mac[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - ndev_vif->iftype = NL80211_IFTYPE_STATION; - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - ndev_vif->vif_type = FAPI_VIFTYPE_STATION; - - if (WARN(slsi_mlme_add_vif(sdev, dev, dev->dev_addr, device_address) != 0, "add VIF failed")) { - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EFAULT; - } - - if (WARN(slsi_vif_activated(sdev, dev) != 0, "activate VIF failed")) { - slsi_mlme_del_vif(sdev, dev); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EFAULT; - } - - peer = slsi_peer_add(sdev, dev, fake_peer_mac, SLSI_STA_PEER_QUEUESET + 1); - if (WARN(!peer, "add fake peer failed")) { - slsi_vif_deactivated(sdev, dev); - slsi_mlme_del_vif(sdev, dev); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EFAULT; - } - peer->qos_enabled = true; - slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED); - netif_carrier_on(dev); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return 0; -} - -static void slsi_src_sink_fake_sta_stop(struct slsi_dev *sdev, struct net_device *dev) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - SLSI_NET_DBG1(dev, SLSI_SRC_SINK, "station stop(vif:%d)\n", ndev_vif->ifnum); - - if (WARN(!ndev_vif->activated, "not activated")) { - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return; - } - - netif_carrier_off(dev); - if (peer) - slsi_peer_remove(sdev, dev, peer); - slsi_vif_deactivated(sdev, dev); - slsi_mlme_del_vif(sdev, dev); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -} - -static int slsi_src_sink_loopback_start(struct slsi_dev *sdev) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - u8 i, queue_idx; - - for (i = SLSI_NET_INDEX_WLAN; i <= SLSI_NET_INDEX_P2P; i++) { - dev = slsi_get_netdev_locked(sdev, i); - if (WARN(!dev, "no netdev (index:%d)", i)) - return -EFAULT; - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - /* for p2p0 interface the peer database is not created during init; - * peer database is needed for dataplane to be functional. - * so create the peer records for p2p0 now and undo it during loopback stop - */ - if (i == SLSI_NET_INDEX_P2P) { - for (queue_idx = 0; queue_idx < SLSI_ADHOC_PEER_CONNECTIONS_MAX; queue_idx++) { - ndev_vif->peer_sta_record[queue_idx] = kzalloc(sizeof(*ndev_vif->peer_sta_record[queue_idx]), GFP_KERNEL); - if (!ndev_vif->peer_sta_record[queue_idx]) { - int j; - - SLSI_NET_ERR(dev, "Could not allocate memory for peer entry (queue_idx:%d)\n", queue_idx); - - /* free previously allocated peer database memory till current queue_idx */ - for (j = 0; j < queue_idx; j++) { - kfree(ndev_vif->peer_sta_record[j]); - ndev_vif->peer_sta_record[j] = NULL; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return -EFAULT; - } - } - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - if (WARN(slsi_src_sink_fake_sta_start(sdev, dev) != 0, "fake STA setup failed (vif:%d)\n", i)) - return -EFAULT; - } - return 0; -} - -static void slsi_src_sink_loopback_stop(struct slsi_dev *sdev) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - u8 i, queue_idx; - - for (i = SLSI_NET_INDEX_WLAN; i <= SLSI_NET_INDEX_P2P; i++) { - dev = slsi_get_netdev_locked(sdev, i); - if (WARN(!dev, "no netdev (index:%d)", i)) - return; - - slsi_src_sink_fake_sta_stop(sdev, dev); - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - /* undo peer database creation for p2p0 interface on loopback stop */ - if (i == SLSI_NET_INDEX_P2P) { - for (queue_idx = 0; queue_idx < SLSI_ADHOC_PEER_CONNECTIONS_MAX; queue_idx++) { - kfree(ndev_vif->peer_sta_record[queue_idx]); - ndev_vif->peer_sta_record[queue_idx] = NULL; - } - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } -} - -long slsi_src_sink_cdev_ioctl_cfg(struct slsi_dev *sdev, unsigned long arg) -{ - long r = 0; - struct unifiio_src_sink_arg_t src_sink_arg; - struct net_device *dev; - struct netdev_vif *ndev_vif; - struct sk_buff *req = NULL; - struct sk_buff *ind = NULL; - - memset((void *)&src_sink_arg, 0, sizeof(struct unifiio_src_sink_arg_t)); - if (copy_from_user((void *)(&src_sink_arg), (void *)arg, sizeof(struct unifiio_src_sink_arg_t))) - return -EFAULT; - - SLSI_DBG2(sdev, SLSI_SRC_SINK, "Source/Sink\n"); - SLSI_DBG2(sdev, SLSI_SRC_SINK, "====================================================\n"); - SLSI_DBG2(sdev, SLSI_SRC_SINK, " #action : [0x%04X]\n", src_sink_arg.common.action); - SLSI_DBG2(sdev, SLSI_SRC_SINK, " #direction : [0x%04X]\n", src_sink_arg.common.direction); - SLSI_DBG2(sdev, SLSI_SRC_SINK, " #vif : [0x%04X]\n", src_sink_arg.common.vif); - SLSI_DBG2(sdev, SLSI_SRC_SINK, " #endpoint : [0x%04X]\n", src_sink_arg.common.endpoint); - SLSI_DBG2(sdev, SLSI_SRC_SINK, "====================================================\n"); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - dev = slsi_get_netdev_locked(sdev, src_sink_arg.common.vif); - if (WARN_ON(!dev)) { - SLSI_ERR(sdev, "netdev for input vif:%d is NULL\n", src_sink_arg.common.vif); - r = -ENODEV; - goto out_locked; - } - ndev_vif = netdev_priv(dev); - - switch (src_sink_arg.common.action) { - case SRC_SINK_ACTION_SINK_START: - if (WARN(slsi_src_sink_fake_sta_start(sdev, dev) != 0, "fake STA setup failed\n")) { - r = -EFAULT; - goto out_locked; - } - req = fapi_alloc(debug_pkt_sink_start_req, DEBUG_PKT_SINK_START_REQ, src_sink_arg.common.vif, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_sink_start_req.end_point, src_sink_arg.common.endpoint); - fapi_set_u16(req, u.debug_pkt_sink_start_req.direction, src_sink_arg.common.direction); - fapi_set_u32(req, u.debug_pkt_sink_start_req.interval, src_sink_arg.u.config.interval); - fapi_set_u16(req, u.debug_pkt_sink_start_req.packets_per_interval, src_sink_arg.u.config.pkts_per_int); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_sink_start_req->\n"); - r = slsi_mlme_req(sdev, dev, req); - break; - case SRC_SINK_ACTION_SINK_STOP: - req = fapi_alloc(debug_pkt_sink_stop_req, DEBUG_PKT_SINK_STOP_REQ, src_sink_arg.common.vif, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_sink_stop_req.direction, src_sink_arg.common.direction); - fapi_set_u16(req, u.debug_pkt_sink_stop_req.end_point, src_sink_arg.common.endpoint); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_sink_stop_req->\n"); - r = slsi_mlme_req(sdev, dev, req); - slsi_src_sink_fake_sta_stop(sdev, dev); - break; - case SRC_SINK_ACTION_GEN_START: - if (WARN(slsi_src_sink_fake_sta_start(sdev, dev) != 0, "fake STA setup failed\n")) { - r = -EFAULT; - goto out_locked; - } - req = fapi_alloc(debug_pkt_gen_start_req, DEBUG_PKT_GEN_START_REQ, src_sink_arg.common.vif, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_gen_start_req.direction, src_sink_arg.common.direction); - fapi_set_u16(req, u.debug_pkt_gen_start_req.end_point, src_sink_arg.common.endpoint); - fapi_set_u32(req, u.debug_pkt_gen_start_req.interval, src_sink_arg.u.config.interval); - fapi_set_u16(req, u.debug_pkt_gen_start_req.packets_per_interval, src_sink_arg.u.config.pkts_per_int); - fapi_set_u16(req, u.debug_pkt_gen_start_req.size, src_sink_arg.u.config.u.gen.size); - fapi_set_u16(req, u.debug_pkt_gen_start_req.use_streaming, src_sink_arg.u.config.u.gen.use_streaming); - fapi_set_u32(req, u.debug_pkt_gen_start_req.ipv4destination_address, src_sink_arg.u.config.u.gen.ipv4_dest); - fapi_set_u16(req, u.debug_pkt_gen_start_req.packets_per_interrupt, src_sink_arg.u.config.u.gen.pkts_per_intr); - - SLSI_DBG3(sdev, SLSI_SRC_SINK, - "int:%u, pkts_per_int:%u, vif:%u, size:%u, use_streaming:%u, ipv4_dest:0x%04X, pkts_per_intr:%u\n", - src_sink_arg.u.config.interval, - src_sink_arg.u.config.pkts_per_int, - src_sink_arg.common.vif, - src_sink_arg.u.config.u.gen.size, - src_sink_arg.u.config.u.gen.use_streaming, - src_sink_arg.u.config.u.gen.ipv4_dest, - src_sink_arg.u.config.u.gen.pkts_per_intr); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_gen_start_req->\n"); - r = slsi_mlme_req(sdev, dev, req); - break; - case SRC_SINK_ACTION_GEN_STOP: - req = fapi_alloc(debug_pkt_gen_stop_req, DEBUG_PKT_GEN_STOP_REQ, src_sink_arg.common.vif, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_gen_stop_req.direction, src_sink_arg.common.direction); - fapi_set_u16(req, u.debug_pkt_gen_stop_req.end_point, src_sink_arg.common.endpoint); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_gen_stop_req->\n"); - r = slsi_mlme_req(sdev, dev, req); - slsi_src_sink_fake_sta_stop(sdev, dev); - break; - case SRC_SINK_ACTION_LOOPBACK_START: - if (WARN(slsi_src_sink_loopback_start(sdev) != 0, "loopback setup failed\n")) { - r = -EFAULT; - goto out_locked; - } - req = fapi_alloc(debug_pkt_sink_start_req, DEBUG_PKT_SINK_START_REQ, 1, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_sink_start_req.end_point, SRC_SINK_ENDPOINT_HOSTIO); - fapi_set_u16(req, u.debug_pkt_sink_start_req.direction, SRC_SINK_DIRECTION_RX); - fapi_set_u32(req, u.debug_pkt_sink_start_req.interval, src_sink_arg.u.config.interval); - fapi_set_u16(req, u.debug_pkt_sink_start_req.packets_per_interval, src_sink_arg.u.config.pkts_per_int); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_loopback_start_req->\n"); - r = slsi_mlme_req(sdev, dev, req); - break; - case SRC_SINK_ACTION_LOOPBACK_STOP: - req = fapi_alloc(debug_pkt_sink_stop_req, DEBUG_PKT_SINK_STOP_REQ, 1, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_sink_stop_req.direction, SRC_SINK_DIRECTION_RX); - fapi_set_u16(req, u.debug_pkt_sink_stop_req.end_point, SRC_SINK_ENDPOINT_HOSTIO); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_loopback_stop_req->\n"); - r = slsi_mlme_req(sdev, dev, req); - slsi_src_sink_loopback_stop(sdev); - break; - case SRC_SINK_ACTION_SINK_REPORT: - req = fapi_alloc(debug_pkt_sink_report_req, DEBUG_PKT_SINK_REPORT_REQ, src_sink_arg.common.vif, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_sink_report_req.end_point, src_sink_arg.common.endpoint); - fapi_set_u16(req, u.debug_pkt_sink_report_req.direction, src_sink_arg.common.direction); - fapi_set_u32(req, u.debug_pkt_sink_report_req.report_interval, src_sink_arg.u.report.interval); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_sink_report_req->\n"); - - ind = slsi_mlme_req_ind(sdev, dev, req, DEBUG_PKT_SINK_REPORT_IND); - if (!ind) { - SLSI_ERR(sdev, "slsi_mlme_req_ind [SINK_REPORT] failed\n"); - r = -EIO; - break; - } - - src_sink_arg.u.report.duration = fapi_get_u32(ind, u.debug_pkt_sink_report_ind.duration); - src_sink_arg.u.report.count = fapi_get_u32(ind, u.debug_pkt_sink_report_ind.received_packets); - src_sink_arg.u.report.octet = fapi_get_u32(ind, u.debug_pkt_sink_report_ind.received_octets); - src_sink_arg.u.report.kbps = fapi_get_u32(ind, u.debug_pkt_sink_report_ind.kbps); - src_sink_arg.u.report.idle_ratio = fapi_get_u16(ind, u.debug_pkt_sink_report_ind.idle_ratio); - src_sink_arg.u.report.interrupt_latency = fapi_get_u16(ind, u.debug_pkt_sink_report_ind.int_latency); - src_sink_arg.u.report.free_kbytes = fapi_get_u16(ind, u.debug_pkt_sink_report_ind.free_kbytes); - src_sink_arg.u.report.timestamp = jiffies_to_msecs(jiffies); - - memset(&ndev_vif->src_sink_params.sink_report, 0, sizeof(struct unifiio_src_sink_report)); - - /* copy the report to userspace */ - if (copy_to_user((void *)arg, (void *)(&src_sink_arg), sizeof(struct unifiio_src_sink_arg_t))) - r = -EFAULT; - slsi_kfree_skb(ind); - break; - case SRC_SINK_ACTION_GEN_REPORT: - req = fapi_alloc(debug_pkt_gen_report_req, DEBUG_PKT_GEN_REPORT_REQ, src_sink_arg.common.vif, 0); - if (WARN_ON(!req)) { - r = -ENODEV; - goto out_locked; - } - fapi_set_u16(req, u.debug_pkt_gen_report_req.end_point, src_sink_arg.common.endpoint); - fapi_set_u16(req, u.debug_pkt_gen_report_req.direction, src_sink_arg.common.direction); - fapi_set_u32(req, u.debug_pkt_gen_report_req.report_interval, src_sink_arg.u.report.interval); - SLSI_DBG1(sdev, SLSI_SRC_SINK, "debug_pkt_gen_report_req->\n"); - - ind = slsi_mlme_req_ind(sdev, dev, req, DEBUG_PKT_GEN_REPORT_IND); - if (!ind) { - SLSI_ERR(sdev, "slsi_mlme_req_ind [GEN_REPORT] failed\n"); - r = -EIO; - break; - } - - src_sink_arg.u.report.duration = fapi_get_u32(ind, u.debug_pkt_gen_report_ind.duration); - src_sink_arg.u.report.count = fapi_get_u32(ind, u.debug_pkt_gen_report_ind.received_packets); - src_sink_arg.u.report.failed_count = fapi_get_u32(ind, u.debug_pkt_gen_report_ind.failed_count); - src_sink_arg.u.report.octet = fapi_get_u32(ind, u.debug_pkt_gen_report_ind.received_octets); - src_sink_arg.u.report.kbps = fapi_get_u32(ind, u.debug_pkt_gen_report_ind.kbps); - src_sink_arg.u.report.idle_ratio = fapi_get_u16(ind, u.debug_pkt_gen_report_ind.idle_ratio); - src_sink_arg.u.report.interrupt_latency = fapi_get_u16(ind, u.debug_pkt_gen_report_ind.int_latency); - src_sink_arg.u.report.free_kbytes = fapi_get_u16(ind, u.debug_pkt_gen_report_ind.free_kbytes); - - src_sink_arg.u.report.timestamp = jiffies_to_msecs(jiffies); - - memset(&ndev_vif->src_sink_params.gen_report, 0, sizeof(struct unifiio_src_sink_report)); - - /* copy the report to userspace */ - if (copy_to_user((void *)arg, (void *)(&src_sink_arg), sizeof(struct unifiio_src_sink_arg_t))) - r = -EFAULT; - slsi_kfree_skb(ind); - break; - case SRC_SINK_ACTION_SINK_REPORT_CACHED: - SLSI_DBG1(sdev, SLSI_SRC_SINK, "cached sink_report\n"); - memcpy(&src_sink_arg.u.report, &ndev_vif->src_sink_params.sink_report, sizeof(struct unifiio_src_sink_report)); - memset(&ndev_vif->src_sink_params.sink_report, 0, sizeof(struct unifiio_src_sink_report)); - - if (copy_to_user((void *)arg, (void *)(&src_sink_arg), sizeof(struct unifiio_src_sink_arg_t))) - r = -EFAULT; - - break; - case SRC_SINK_ACTION_GEN_REPORT_CACHED: - SLSI_DBG1(sdev, SLSI_SRC_SINK, "cached gen_report\n"); - memcpy(&src_sink_arg.u.report, &ndev_vif->src_sink_params.gen_report, sizeof(struct unifiio_src_sink_report)); - memset(&ndev_vif->src_sink_params.gen_report, 0, sizeof(struct unifiio_src_sink_report)); - - if (copy_to_user((void *)arg, (void *)(&src_sink_arg), sizeof(struct unifiio_src_sink_arg_t))) - r = -EFAULT; - break; - default: - SLSI_ERR(sdev, "Invalid input for action: 0x%04X\n", src_sink_arg.common.action); - r = -EINVAL; - break; - } - -out_locked: - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - if (r) - SLSI_ERR(sdev, "slsi_src_sink_cdev_ioctl_cfg(vif:%d) failed with %ld\n", src_sink_arg.common.vif, r); - return r; -} - -void slsi_rx_sink_report(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct unifiio_src_sink_report *report = &ndev_vif->src_sink_params.sink_report; - - SLSI_DBG3(sdev, SLSI_SRC_SINK, "RX debug_pkt_sink_report_ind\n"); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - memset(report, 0, sizeof(struct unifiio_src_sink_report)); - report->duration = fapi_get_u32(skb, u.debug_pkt_sink_report_ind.duration); - report->count = fapi_get_u32(skb, u.debug_pkt_sink_report_ind.received_packets); - report->octet = fapi_get_u32(skb, u.debug_pkt_sink_report_ind.received_octets); - report->kbps = fapi_get_u32(skb, u.debug_pkt_sink_report_ind.kbps); - report->idle_ratio = fapi_get_u16(skb, u.debug_pkt_sink_report_ind.idle_ratio); - report->interrupt_latency = fapi_get_u16(skb, u.debug_pkt_sink_report_ind.int_latency); - report->free_kbytes = fapi_get_u16(skb, u.debug_pkt_sink_report_ind.free_kbytes); - report->timestamp = jiffies_to_msecs(jiffies); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - slsi_kfree_skb(skb); -} - -void slsi_rx_gen_report(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct unifiio_src_sink_report *report = &ndev_vif->src_sink_params.gen_report; - - SLSI_DBG3(sdev, SLSI_SRC_SINK, "RX debug_pkt_gen_report_ind\n"); - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - memset(report, 0, sizeof(struct unifiio_src_sink_report)); - report->duration = fapi_get_u32(skb, u.debug_pkt_gen_report_ind.duration); - report->count = fapi_get_u32(skb, u.debug_pkt_gen_report_ind.received_packets); - report->failed_count = fapi_get_u32(skb, u.debug_pkt_gen_report_ind.failed_count); - report->octet = fapi_get_u32(skb, u.debug_pkt_gen_report_ind.received_octets); - report->kbps = fapi_get_u32(skb, u.debug_pkt_gen_report_ind.kbps); - report->idle_ratio = fapi_get_u16(skb, u.debug_pkt_gen_report_ind.idle_ratio); - report->interrupt_latency = fapi_get_u16(skb, u.debug_pkt_gen_report_ind.int_latency); - report->free_kbytes = fapi_get_u16(skb, u.debug_pkt_gen_report_ind.free_kbytes); - report->timestamp = jiffies_to_msecs(jiffies); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - slsi_kfree_skb(skb); -} diff --git a/drivers/net/wireless/scsc/src_sink.h b/drivers/net/wireless/scsc/src_sink.h deleted file mode 100644 index d9387e87c251..000000000000 --- a/drivers/net/wireless/scsc/src_sink.h +++ /dev/null @@ -1,22 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_SRC_SINK_H__ -#define __SLSI_SRC_SINK_H__ - -#include "unifiio.h" - -struct slsi_src_sink_params { - struct unifiio_src_sink_report sink_report; - struct unifiio_src_sink_report gen_report; -}; - -long slsi_src_sink_cdev_ioctl_cfg(struct slsi_dev *sdev, unsigned long arg); - -void slsi_rx_sink_report(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_rx_gen_report(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); - -#endif /* __SLSI_SRC_SINK_H__ */ diff --git a/drivers/net/wireless/scsc/test/Makefile b/drivers/net/wireless/scsc/test/Makefile deleted file mode 100755 index 8d36b9e6fe70..000000000000 --- a/drivers/net/wireless/scsc/test/Makefile +++ /dev/null @@ -1,108 +0,0 @@ - # ---------------------------------------------------------------------------- -# FILE: Makefile -# -# PURPOSE: -# Build instructions for SCSC Wlan driver. -# -# -# Copyright (C) 2016 by Samsung Electronics Co., Ltd -# ---------------------------------------------------------------------------- - -CONFIG_SCSC_WLAN_MODULE=scsc_wlan_unittest - -# ---------------------------------------------------------------------------- -# Common Driver Files -# ---------------------------------------------------------------------------- -$(CONFIG_SCSC_WLAN_MODULE)-y += ../mib.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../mib_text_convert.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../debug.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../debug_frame.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../procfs.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../mgt.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../udi.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../log_clients.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../src_sink.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../fw_test.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../cac.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../ioctl.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../wakelock.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../traffic_monitor.o -# enable GSCAN -ifeq ($(CONFIG_SCSC_WLAN_GSCAN_ENABLE),y) -$(CONFIG_SCSC_WLAN_MODULE)-y += ../nl80211_vendor.o -ccflags-y += -DCONFIG_SCSC_WLAN_GSCAN_ENABLE -endif - -# enable roam offload -ifeq ($(CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD),y) -ccflags-y += -DCONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD -endif - -# ---------------------------------------------------------------------------- -# Building for cfg802.11 -# ---------------------------------------------------------------------------- -$(CONFIG_SCSC_WLAN_MODULE)-y += ../cfg80211_ops.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../mlme.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../netif.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../rx.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../tx.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../ba.o - -# ---------------------------------------------------------------------------- -# Building for SAP -# ---------------------------------------------------------------------------- -$(CONFIG_SCSC_WLAN_MODULE)-y += ../sap_ma.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../sap_mlme.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../sap_dbg.o -$(CONFIG_SCSC_WLAN_MODULE)-y += ../sap_test.o - -# ---------------------------------------------------------------------------- -# unittest Driver -# ---------------------------------------------------------------------------- -$(CONFIG_SCSC_WLAN_MODULE)-y += ../dev.o -$(CONFIG_SCSC_WLAN_MODULE)-y += dev_test.o -$(CONFIG_SCSC_WLAN_MODULE)-y += hip_test.o -$(CONFIG_SCSC_WLAN_MODULE)-y += hydra_test.o -$(CONFIG_SCSC_WLAN_MODULE)-y += udi_test.o - -# Suppress -Wempty-body when not built with Debug enabled. -ifneq ($(CONFIG_SCSC_WLAN_DEBUG),y) -ccflags-y += -Wno-empty-body -else -ccflags-y += -g -ggdb -endif - -ccflags-y += -Wno-unused-parameter -ccflags-y += -Wno-sign-compare - -# ---------------------------------------------------------------------------- -# wlan configuration -# ---------------------------------------------------------------------------- -ccflags-$(CONFIG_SCSC_WLAN_DEBUG) += -DCONFIG_SCSC_WLAN_DEBUG -ccflags-$(CONFIG_SCSC_WLAN_SKB_TRACKING) += -DCONFIG_SCSC_WLAN_SKB_TRACKING -ccflags-$(CONFIG_SCSC_WLAN_OFFLINE_TRACE) += -DCONFIG_SCSC_WLAN_OFFLINE_TRACE -ccflags-$(CONFIG_SCSC_WLAN_OFFLINE_SDIO_TRACE) += -DCONFIG_SCSC_WLAN_OFFLINE_SDIO_TRACE -ccflags-$(CONFIG_SCSC_WLAN_OFFLINE_DATA_PLANE_PROFILE_TRACE) += -DCONFIG_SCSC_WLAN_OFFLINE_DATA_PLANE_PROFILE_TRACE -ccflags-$(CONFIG_SCSC_WLAN_OFFLINE_TX_TRACE) += -DCONFIG_SCSC_WLAN_OFFLINE_TX_TRACE -ccflags-$(CONFIG_SCSC_WLAN_HIP_CLEAR_TH_SLOT_SUPPORT) += -DCONFIG_SCSC_WLAN_HIP_CLEAR_TH_SLOT_SUPPORT -ccflags-$(CONFIG_SCSC_WLAN_HIP_DEFER_SLOT_SUPPORT) += -DCONFIG_SCSC_WLAN_HIP_DEFER_SLOT_SUPPORT -ccflags-$(CONFIG_SCSC_WLAN_RX_NAPI) += -DCONFIG_SCSC_WLAN_RX_NAPI -ccflags-$(CONFIG_SCSC_WLAN_RX_NAPI_GRO) += -DCONFIG_SCSC_WLAN_RX_NAPI_GRO -ccflags-$(CONFIG_SCSC_WLAN_WES_NCHO) += -DCONFIG_SCSC_WLAN_WES_NCHO -ccflags-$(CONFIG_SCSC_WLAN_MUTEX_DEBUG) += -DCONFIG_SCSC_WLAN_MUTEX_DEBUG - -ccflags-y += -DCONFIG_SCSC_WLAN_MAX_INTERFACES=$(CONFIG_SCSC_WLAN_MAX_INTERFACES) - -# Android specific build options -ccflags-$(CONFIG_SCSC_WLAN_ANDROID) += -DCONFIG_SCSC_WLAN_ANDROID - -ccflags-y += -I$(src) -I$(src)/.. -ccflags-y += -I$(src)/../../../../../include -I$(src)/../../../../../include/scsc - -ccflags-y += -DSLSI_TEST_DEV -ccflags-y += $(CONFIG_SCSC_WLAN_EXTRA) - -# ---------------------------------------------------------------------------- -# module -# ---------------------------------------------------------------------------- -obj-$(CONFIG_SCSC_WLAN_UNITTEST) := $(CONFIG_SCSC_WLAN_MODULE).o diff --git a/drivers/net/wireless/scsc/test/dev_test.c b/drivers/net/wireless/scsc/test/dev_test.c deleted file mode 100755 index 874132144a5b..000000000000 --- a/drivers/net/wireless/scsc/test/dev_test.c +++ /dev/null @@ -1,511 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd - * - ****************************************************************************/ - -#include - -#include "debug.h" -#include "utils.h" -#include "udi.h" -#include "unittest.h" -#include "mgt.h" -#include "scsc/scsc_mx.h" - -#define SLSI_TESTDRV_NAME "s5n2560_test" - -static int radios = 11; -module_param(radios, int, 0444); -MODULE_PARM_DESC(radios, "Number of simulated radios"); - -/* spinlock for retaining the (struct slsi_dev) information */ -static struct slsi_spinlock slsi_test_devices_lock; -static struct slsi_test_dev *slsi_test_devices[SLSI_UDI_MINOR_NODES]; - -static struct class *test_dev_class; -/* Major number of device created by system. */ -static dev_t major_number; - -static struct device_driver slsi_test_driver = { - .name = SLSI_TESTDRV_NAME -}; - -static void slsi_test_dev_attach_work(struct work_struct *work); -static void slsi_test_dev_detach_work(struct work_struct *work); - -static void slsi_test_dev_free(void) -{ - int i; - - for (i = 0; i < SLSI_UDI_MINOR_NODES; i++) { - struct slsi_test_dev *uftestdev; - - slsi_spinlock_lock(&slsi_test_devices_lock); - uftestdev = slsi_test_devices[i]; - slsi_test_devices[i] = NULL; - slsi_spinlock_unlock(&slsi_test_devices_lock); - if (uftestdev != NULL) { - SLSI_INFO_NODEV("Free Test Device: %02X:%02X:%02X:%02X:%02X:%02X\n", - uftestdev->hw_addr[0], - uftestdev->hw_addr[1], - uftestdev->hw_addr[2], - uftestdev->hw_addr[3], - uftestdev->hw_addr[4], - uftestdev->hw_addr[5]); - - if (WARN_ON(uftestdev->attached)) { - slsi_test_bh_deinit(uftestdev); - flush_workqueue(uftestdev->attach_detach_work_queue); - } - destroy_workqueue(uftestdev->attach_detach_work_queue); - - slsi_test_udi_node_deinit(uftestdev); - - device_unregister(uftestdev->dev); - device_destroy(test_dev_class, uftestdev->dev->devt); - } - } - - slsi_test_udi_deinit(); - - if (test_dev_class != NULL) - class_destroy(test_dev_class); - - unregister_chrdev_region(major_number, SLSI_UDI_MINOR_NODES); -} - -int slsi_sdio_func_drv_register(void) -{ - int i = 0, err = 0, ret = 0; - struct slsi_test_dev *uftestdev; - dev_t devno; - - SLSI_INFO_NODEV("Loading SLSI " SLSI_TESTDRV_NAME " Test Driver for mac80211\n"); - - if (radios > SLSI_UDI_MINOR_NODES) { - SLSI_ERR_NODEV("Loading failed, configure SLSI_UDI_MINOR_NODES to match no. of simulated radios\n"); - return -ENOMEM; - } - - slsi_spinlock_create(&slsi_test_devices_lock); - memset(slsi_test_devices, 0x00, sizeof(slsi_test_devices)); - - /* Allocate two device numbers for each device. */ - ret = alloc_chrdev_region(&major_number, 0, SLSI_UDI_MINOR_NODES, SLSI_TESTDRV_NAME); - if (ret) { - SLSI_ERR_NODEV("Failed to add alloc dev numbers: %d\n", ret); - unregister_chrdev_region(major_number, SLSI_UDI_MINOR_NODES); - major_number = 0; - return -ENOMEM; - } - - test_dev_class = class_create(THIS_MODULE, SLSI_TESTDRV_NAME); - if (IS_ERR(test_dev_class)) - return -EAGAIN; - - slsi_test_udi_init(); - - for (i = 0; i < radios; i++) { - uftestdev = kmalloc(sizeof(*uftestdev), GFP_KERNEL); - memset(uftestdev, 0, sizeof(*uftestdev)); - uftestdev->attach_detach_work_queue = alloc_ordered_workqueue("Test Work", 0); - INIT_WORK(&uftestdev->attach_work, slsi_test_dev_attach_work); - INIT_WORK(&uftestdev->detach_work, slsi_test_dev_detach_work); - - devno = MKDEV(MAJOR(major_number), i); - - uftestdev->dev = device_create(test_dev_class, NULL, devno, uftestdev, SLSI_TESTDRV_NAME "_dev%d", i); - if (IS_ERR(uftestdev->dev)) { - SLSI_ERR_NODEV("device_create FAILED, returned - (%ld)\n", PTR_ERR(uftestdev->dev)); - err = -ENOMEM; - goto failed_free_all; - } - - uftestdev->dev->driver = &slsi_test_driver; - - mutex_init(&uftestdev->attach_detach_mutex); - slsi_test_bh_init(uftestdev); - spin_lock_init(&uftestdev->route_spinlock); - - if (slsi_test_udi_node_init(uftestdev, uftestdev->dev) != 0) { - SLSI_ERR_NODEV("udi init FAILED\n"); - goto failed_dev_unregister; - } - - /* Using a fixed MAC address instead of slsi_get_hw_mac_address(), - * MAC Address format 00:12:FB:00:00: where xx increments for every PHY - * (00:12:FB OUI Samsung Electronics) - */ - - memset(uftestdev->hw_addr, 0, sizeof(uftestdev->hw_addr)); - uftestdev->hw_addr[1] = 0x12; - uftestdev->hw_addr[2] = 0xFB; - /*To randomize the mac address*/ - uftestdev->hw_addr[ETH_ALEN - 1] += (i & (0xff)); - - SLSI_INFO_NODEV("Create Test Device: %02X:%02X:%02X:%02X:%02X:%02X\n", - uftestdev->hw_addr[0], - uftestdev->hw_addr[1], - uftestdev->hw_addr[2], - uftestdev->hw_addr[3], - uftestdev->hw_addr[4], - uftestdev->hw_addr[5]); - slsi_test_devices[uftestdev->device_minor_number] = uftestdev; - } - - return 0; - -failed_dev_unregister: - device_unregister(uftestdev->dev); - device_destroy(test_dev_class, uftestdev->dev->devt); -failed_free_all: - slsi_test_dev_free(); - - return -EPERM; -} - -void slsi_sdio_func_drv_unregister(void) -{ - SLSI_INFO_NODEV("Unloading UF6K Test Driver for mac80211\n"); - slsi_test_dev_free(); -} - -void slsi_test_dev_attach(struct slsi_test_dev *uftestdev) -{ - struct slsi_dev *sdev; - struct scsc_service_client service_client; - - mutex_lock(&uftestdev->attach_detach_mutex); - SLSI_INFO_NODEV("UnitTest UDI Attached : %02X:%02X:%02X:%02X:%02X:%02X\n", - uftestdev->hw_addr[0], - uftestdev->hw_addr[1], - uftestdev->hw_addr[2], - uftestdev->hw_addr[3], - uftestdev->hw_addr[4], - uftestdev->hw_addr[5]); - - if (uftestdev->attached) { - SLSI_ERR_NODEV("attached == true\n"); - goto exit; - } - - uftestdev->attached = true; - sdev = slsi_dev_attach(uftestdev->dev, (struct scsc_mx *)uftestdev, &service_client); - - slsi_spinlock_lock(&slsi_test_devices_lock); - uftestdev->sdev = sdev; - if (!sdev) { - SLSI_ERR_NODEV("slsi_dev_attach() Failed\n"); - uftestdev->attached = false; - } else { - slsi_test_bh_start(uftestdev); - } - - slsi_spinlock_unlock(&slsi_test_devices_lock); - -exit: - mutex_unlock(&uftestdev->attach_detach_mutex); -} - -void slsi_test_dev_detach(struct slsi_test_dev *uftestdev) -{ - mutex_lock(&uftestdev->attach_detach_mutex); - SLSI_INFO(uftestdev->sdev, "UnitTest UDI Detached : %02X:%02X:%02X:%02X:%02X:%02X\n", - uftestdev->hw_addr[0], - uftestdev->hw_addr[1], - uftestdev->hw_addr[2], - uftestdev->hw_addr[3], - uftestdev->hw_addr[4], - uftestdev->hw_addr[5]); - if (!uftestdev->attached) { - SLSI_ERR(uftestdev->sdev, "attached != true\n"); - goto exit; - } - - uftestdev->attached = false; - if (uftestdev->sdev) { - struct slsi_dev *sdev = uftestdev->sdev; - - slsi_test_bh_stop(uftestdev); - - slsi_dev_detach(sdev); - slsi_spinlock_lock(&slsi_test_devices_lock); - uftestdev->sdev = NULL; - slsi_spinlock_unlock(&slsi_test_devices_lock); - } - -exit: - mutex_unlock(&uftestdev->attach_detach_mutex); -} - -void slsi_init_netdev_mac_addr(struct slsi_dev *sdev) -{ - /* Get mac address from file system. */ - slsi_get_hw_mac_address(sdev, sdev->hw_addr); - - SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_WLAN], sdev->hw_addr); - - SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_P2P], sdev->hw_addr); - sdev->netdev_addresses[SLSI_NET_INDEX_P2P][0] |= 0x02; /* Set the local bit */ - - SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN], sdev->hw_addr); - sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][0] |= 0x02; /* Set the local bit */ - sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][4] ^= 0x80; /* EXOR 5th byte with 0x80 */ - - SLSI_ETHER_COPY(sdev->netdev[SLSI_NET_INDEX_WLAN]->dev_addr, sdev->netdev_addresses[SLSI_NET_INDEX_WLAN]); - SLSI_ETHER_COPY(sdev->netdev[SLSI_NET_INDEX_P2P]->dev_addr, sdev->netdev_addresses[SLSI_NET_INDEX_P2P]); -} - -bool slsi_test_process_signal_ip_remap(struct slsi_test_dev *uftestdev, struct sk_buff *skb, struct slsi_test_data_route *route) -{ - int proto = ntohs(skb->protocol); - u8 *frame = fapi_get_data(skb) + 14; - - switch (proto) { - case 0x0806: - { - /* Arp */ - u8 *sha = &frame[8]; - u8 *spa = &frame[14]; - u8 *tha = &frame[18]; - u8 *tpa = &frame[24]; - - SLSI_UNUSED_PARAMETER(sha); - SLSI_UNUSED_PARAMETER(spa); - SLSI_UNUSED_PARAMETER(tha); - SLSI_UNUSED_PARAMETER(tpa); - - SLSI_DBG4(uftestdev->sdev, SLSI_TEST, "ARP: sha:%pM, spa:%d.%d.%d.%d, tha:%pM, tpa:%d.%d.%d.%d\n", - sha, spa[0], spa[1], spa[2], spa[3], - tha, tpa[0], tpa[1], tpa[2], tpa[3]); - spa[2] = route->ipsubnet; - tpa[2] = route->ipsubnet; - SLSI_DBG4(uftestdev->sdev, SLSI_TEST, "ARP: sha:%pM, spa:%d.%d.%d.%d, tha:%pM, tpa:%d.%d.%d.%d\n", - sha, spa[0], spa[1], spa[2], spa[3], - tha, tpa[0], tpa[1], tpa[2], tpa[3]); - return true; - } - case 0x0800: - { - /* IPv4 */ - struct iphdr *iph = (struct iphdr *)frame; - u8 *src = (u8 *)&iph->saddr; - u8 *dst = (u8 *)&iph->daddr; - - SLSI_UNUSED_PARAMETER(src); - SLSI_UNUSED_PARAMETER(dst); - - SLSI_DBG4(uftestdev->sdev, SLSI_TEST, "PING: src:%d.%d.%d.%d, dst:%d.%d.%d.%d, check:0x%.4X\n", - src[0], src[1], src[2], src[3], - dst[0], dst[1], dst[2], dst[3], - iph->check); - src[2] = route->ipsubnet; - dst[2] = route->ipsubnet; - - /* Calculation of IP header checksum */ - iph->check = 0; - ip_send_check(iph); - - SLSI_DBG4(uftestdev->sdev, SLSI_TEST, "PING: src:%d.%d.%d.%d, dst:%d.%d.%d.%d, check:0x%.4X\n", - src[0], src[1], src[2], src[3], - dst[0], dst[1], dst[2], dst[3], - iph->check); - - return true; - } - default: - SLSI_DBG4(uftestdev->sdev, SLSI_TEST, "Proto:0x%.4X\n", proto); - break; - } - return false; -} - -static struct slsi_test_data_route *slsi_test_process_signal_get_route(struct slsi_test_dev *uftestdev, const u8 *mac) -{ - struct slsi_test_data_route *route; - int i; - - if (WARN_ON(!spin_is_locked(&uftestdev->route_spinlock))) - return NULL; - - for (i = 0; i < SLSI_AP_PEER_CONNECTIONS_MAX; i++) { - route = &uftestdev->route[i]; - if (route->configured && ether_addr_equal(route->mac, mac)) - return route; - } - - return NULL; -} - -static struct slsi_test_data_route *slsi_test_process_signal_get_free_route(struct slsi_test_dev *uftestdev) -{ - struct slsi_test_data_route *route; - int i; - - if (WARN_ON(!spin_is_locked(&uftestdev->route_spinlock))) - return NULL; - - for (i = 0; i < SLSI_AP_PEER_CONNECTIONS_MAX; i++) { - route = &uftestdev->route[i]; - if (!route->configured) - return route; - } - - return NULL; -} - -void slsi_test_process_signal_set_route(struct slsi_test_dev *uftestdev, struct sk_buff *skb) -{ - struct slsi_test_data_route *route; - u8 mac[ETH_ALEN]; - u16 dest_device_minor_number = 0xFFFF; - int i; - - mac[0] = fapi_get_buff(skb, u.debug_generic_req.debug_words[2]) >> 8; - mac[1] = fapi_get_buff(skb, u.debug_generic_req.debug_words[2]) & 0xFF; - mac[2] = fapi_get_buff(skb, u.debug_generic_req.debug_words[3]) >> 8; - mac[3] = fapi_get_buff(skb, u.debug_generic_req.debug_words[3]) & 0xFF; - mac[4] = fapi_get_buff(skb, u.debug_generic_req.debug_words[4]) >> 8; - mac[5] = fapi_get_buff(skb, u.debug_generic_req.debug_words[4]) & 0xFF; - - slsi_spinlock_lock(&slsi_test_devices_lock); - for (i = 0; i < SLSI_UDI_MINOR_NODES; i++) { - struct slsi_test_dev *destdev = slsi_test_devices[i]; - - if (destdev != NULL && ether_addr_equal(destdev->hw_addr, mac)) - dest_device_minor_number = destdev->device_minor_number; - } - slsi_spinlock_unlock(&slsi_test_devices_lock); - - if (dest_device_minor_number == 0xFFFF) { - SLSI_ERR(uftestdev->sdev, "Setting Route for %pM FAILED. No match found\n", mac); - return; - } - spin_lock(&uftestdev->route_spinlock); - route = slsi_test_process_signal_get_route(uftestdev, mac); - if (!route) - route = slsi_test_process_signal_get_free_route(uftestdev); - - if (route) { - SLSI_DBG1(uftestdev->sdev, SLSI_TEST, "Setting Route for %pM -> %pM\n", uftestdev->hw_addr, mac); - route->configured = true; - route->test_device_minor_number = dest_device_minor_number; - SLSI_ETHER_COPY(route->mac, mac); - route->vif = fapi_get_u16(skb, u.debug_generic_req.debug_words[5]); - route->ipsubnet = fapi_get_u16(skb, u.debug_generic_req.debug_words[6]) & 0xFF; - route->sequence_number = 1; - } else { - SLSI_ERR(uftestdev->sdev, "Setting Route for %pM FAILED. No Free Route Entry\n", mac); - } - - spin_unlock(&uftestdev->route_spinlock); -} - -void slsi_test_process_signal_clear_route(struct slsi_test_dev *uftestdev, struct sk_buff *skb) -{ - struct slsi_test_data_route *route; - u8 mac[ETH_ALEN]; - - mac[0] = fapi_get_buff(skb, u.debug_generic_req.debug_words[2]) >> 8; - mac[1] = fapi_get_buff(skb, u.debug_generic_req.debug_words[2]) & 0xFF; - mac[2] = fapi_get_buff(skb, u.debug_generic_req.debug_words[3]) >> 8; - mac[3] = fapi_get_buff(skb, u.debug_generic_req.debug_words[3]) & 0xFF; - mac[4] = fapi_get_buff(skb, u.debug_generic_req.debug_words[4]) >> 8; - mac[5] = fapi_get_buff(skb, u.debug_generic_req.debug_words[4]) & 0xFF; - - spin_lock(&uftestdev->route_spinlock); - SLSI_DBG1(uftestdev->sdev, SLSI_TEST, "Clearing Route for %pM\n", mac); - route = slsi_test_process_signal_get_route(uftestdev, mac); - if (route) - route->configured = false; - else - SLSI_ERR(uftestdev->sdev, "Clearing Route for %pM FAILED. No Route Entry Found\n", mac); - spin_unlock(&uftestdev->route_spinlock); -} - -bool slsi_test_process_signal(struct slsi_test_dev *uftestdev, struct sk_buff *skb) -{ - if (fapi_get_sigid(skb) == DEBUG_GENERIC_REQ) { - SLSI_DBG1(uftestdev->sdev, SLSI_TEST, "fapi_get_u16(skb, u.debug_generic_req.debug_words[0]) = %d\n", fapi_get_u16(skb, u.debug_generic_req.debug_words[0])); - SLSI_DBG1(uftestdev->sdev, SLSI_TEST, "fapi_get_u16(skb, u.debug_generic_req.debug_words[1]) = %d\n", fapi_get_u16(skb, u.debug_generic_req.debug_words[1])); - if (fapi_get_u16(skb, u.debug_generic_req.debug_words[0]) == 0x1357) { - if (fapi_get_u16(skb, u.debug_generic_req.debug_words[1]) == 0) - queue_work(uftestdev->attach_detach_work_queue, &uftestdev->detach_work); - else if (fapi_get_u16(skb, u.debug_generic_req.debug_words[1]) == 1) - queue_work(uftestdev->attach_detach_work_queue, &uftestdev->attach_work); - else if (fapi_get_u16(skb, u.debug_generic_req.debug_words[1]) == 2) - slsi_test_process_signal_set_route(uftestdev, skb); - else if (fapi_get_u16(skb, u.debug_generic_req.debug_words[1]) == 3) - slsi_test_process_signal_clear_route(uftestdev, skb); - } - slsi_kfree_skb(skb); - return true; - } - - /* Automatically route the packet to the other test device and bypass the */ - if (fapi_get_sigid(skb) == MA_UNITDATA_REQ) { - struct slsi_test_data_route *route; - struct ethhdr *ehdr = (struct ethhdr *)skb->data; - - spin_lock(&uftestdev->route_spinlock); - route = slsi_test_process_signal_get_route(uftestdev, ehdr->h_dest); - if (route && slsi_test_process_signal_ip_remap(uftestdev, skb, route)) { - struct slsi_skb_cb *cb; - struct fapi_signal req = *((struct fapi_signal *)skb->data); - struct fapi_signal *ind; - - /* Convert the MA_UNITDATA_REQ to a MA_UNITDATA_IND */ - WARN_ON(!skb_pull(skb, fapi_sig_size(ma_unitdata_req))); - ind = (struct fapi_signal *)skb_push(skb, fapi_sig_size(ma_unitdata_ind)); - if (WARN_ON(!ind)) { - slsi_kfree_skb(skb); - spin_unlock(&uftestdev->route_spinlock); - return true; - } - - ind->id = cpu_to_le16(MA_UNITDATA_IND); - ind->receiver_pid = 0; - ind->sender_pid = 0; - fapi_set_u16(skb, u.ma_unitdata_ind.vif, cpu_to_le16(route->vif)); - fapi_set_u16(skb, u.ma_unitdata_ind.sequence_number, route->sequence_number++); - - cb = slsi_skb_cb_init(skb); - cb->sig_length = fapi_get_expected_size(skb); - cb->data_length = skb->len; - - slsi_spinlock_lock(&slsi_test_devices_lock); - if (slsi_test_devices[route->test_device_minor_number] && - slsi_test_devices[route->test_device_minor_number]->sdev) { - if (slsi_hip_rx(slsi_test_devices[route->test_device_minor_number]->sdev, skb) != 0) - slsi_kfree_skb(skb); - } else { - route->configured = false; - slsi_kfree_skb(skb); - } - slsi_spinlock_unlock(&slsi_test_devices_lock); - spin_unlock(&uftestdev->route_spinlock); - return true; - } - spin_unlock(&uftestdev->route_spinlock); - } - - return false; -} - -static void slsi_test_dev_attach_work(struct work_struct *work) -{ - struct slsi_test_dev *uftestdev = container_of(work, struct slsi_test_dev, attach_work); - - SLSI_INFO_NODEV("UnitTest TEST Attach\n"); - slsi_test_dev_attach(uftestdev); - slsi_test_udi_node_reregister(uftestdev); -} - -static void slsi_test_dev_detach_work(struct work_struct *work) -{ - struct slsi_test_dev *uftestdev = container_of(work, struct slsi_test_dev, detach_work); - - SLSI_INFO(uftestdev->sdev, "UnitTest TEST Detach\n"); - slsi_test_dev_detach(uftestdev); -} diff --git a/drivers/net/wireless/scsc/test/hip_test.c b/drivers/net/wireless/scsc/test/hip_test.c deleted file mode 100755 index e576467f7420..000000000000 --- a/drivers/net/wireless/scsc/test/hip_test.c +++ /dev/null @@ -1,276 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include - -#include "unittest.h" -#include "hip.h" -#include "sap.h" -#include "debug.h" -#include "procfs.h" -#include "hip4.h" - -#define SLSI_TEST_DEV_SDIO_BLOCK_SIZE 500 -bool hip4_sampler_sample_start_stop_q = true; -struct hip4_hip_control test_hip_control; - -/* SAP implementations container. Local and static to hip */ -static struct hip_sap { - struct sap_api *sap[SAP_TOTAL]; -} hip_sap_cont; - -/* Register SAP with HIP layer */ -int slsi_hip_sap_register(struct sap_api *sap_api) -{ - u8 class = sap_api->sap_class; - - if (class >= SAP_TOTAL) - return -ENODEV; - - hip_sap_cont.sap[class] = sap_api; - - return 0; -} - -/* UNregister SAP with HIP layer */ -int slsi_hip_sap_unregister(struct sap_api *sap_api) -{ - u8 class = sap_api->sap_class; - - if (class >= SAP_TOTAL) - return -ENODEV; - - hip_sap_cont.sap[class] = NULL; - - return 0; -} - -int slsi_hip_sap_setup(struct slsi_dev *sdev) -{ - /* Execute callbacks to intorm Supported version */ - u16 version = 0; - - if (hip_sap_cont.sap[SAP_MLME]->sap_version_supported) { - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_mlme_ver); - if (hip_sap_cont.sap[SAP_MLME]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - if (hip_sap_cont.sap[SAP_MA]->sap_version_supported) { - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_ma_ver); - if (hip_sap_cont.sap[SAP_MA]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - if (hip_sap_cont.sap[SAP_DBG]->sap_version_supported) { - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_debug_ver); - if (hip_sap_cont.sap[SAP_DBG]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - if (hip_sap_cont.sap[SAP_TST]->sap_version_supported) { - version = scsc_wifi_get_hip_config_version_4_u16(&sdev->hip4_inst.hip_control->config_v4, sap_test_ver); - if (hip_sap_cont.sap[SAP_TST]->sap_version_supported(version)) - return -ENODEV; - } else { - return -ENODEV; - } - - /* Success */ - return 0; -} - -/* SAP rx proxy */ -int slsi_hip_rx(struct slsi_dev *sdev, struct sk_buff *skb) -{ - u16 pid; - - /* Udi test : If pid in UDI range then pass to UDI and ignore */ - slsi_log_clients_log_signal_fast(sdev, &sdev->log_clients, skb, SLSI_LOG_DIRECTION_TO_HOST); - pid = fapi_get_u16(skb, receiver_pid); - if (pid >= SLSI_TX_PROCESS_ID_UDI_MIN && pid <= SLSI_TX_PROCESS_ID_UDI_MAX) { - slsi_kfree_skb(skb); - return 0; - } - - if (fapi_is_ma(skb)) - return hip_sap_cont.sap[SAP_MA]->sap_handler(sdev, skb); - - if (fapi_is_mlme(skb)) - return hip_sap_cont.sap[SAP_MLME]->sap_handler(sdev, skb); - - if (fapi_is_debug(skb)) - return hip_sap_cont.sap[SAP_DBG]->sap_handler(sdev, skb); - - if (fapi_is_test(skb)) - return hip_sap_cont.sap[SAP_TST]->sap_handler(sdev, skb); - - return -EIO; -} - -/* value used at all levels in the driver */ -int slsi_hip_init(struct slsi_dev *sdev, struct device *dev) -{ - SLSI_UNUSED_PARAMETER(dev); - - memset(&sdev->hip, 0, sizeof(sdev->hip)); - - sdev->hip.sdev = sdev; - mutex_init(&sdev->hip.hip_mutex); - - sdev->hip4_inst.hip_control = &test_hip_control; - return 0; -} - -void slsi_hip_deinit(struct slsi_dev *sdev) -{ - mutex_destroy(&sdev->hip.hip_mutex); -} - -int slsi_hip_stop(struct slsi_dev *sdev) -{ - return 0; -} - -int hip4_free_ctrl_slots_count(struct slsi_hip4 *hip) -{ - return HIP4_CTL_SLOTS; -} - -int scsc_wifi_transmit_frame(struct slsi_hip4 *hip, bool ctrl_packet, struct sk_buff *skb) -{ - struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst); - - slsi_log_clients_log_signal_fast(sdev, &sdev->log_clients, skb, SLSI_LOG_DIRECTION_FROM_HOST); - - slsi_kfree_skb(skb); - - return 0; -} - -void slsi_test_bh_work_f(struct work_struct *work) -{ -} - -/* ALL Dummies to get UT build through goes below */ -bool hip4_sampler_sample_q; -bool hip4_sampler_sample_qref; -bool hip4_sampler_sample_int; -bool hip4_sampler_sample_fapi; -bool hip4_sampler_sample_through; -bool hip4_sampler_sample_start_stop_q; -bool hip4_sampler_sample_mbulk; -bool hip4_sampler_sample_qfull; -bool hip4_sampler_sample_mfull; -bool hip4_sampler_vif; -bool hip4_sampler_bot; -bool hip4_sampler_pkt_tx; - -void hip4_sampler_update_record(u32 minor, u8 param1, u8 param2, u8 param3, u8 param4) -{ -} - -void hip4_sampler_create(struct slsi_dev *sdev, struct scsc_mx *mx) -{ -} - -void hip4_sampler_destroy(struct slsi_dev *sdev, struct scsc_mx *mx) -{ -} - -int hip4_sampler_register_hip(struct scsc_mx *mx) -{ - return 0; -} - -int scsc_wifi_fcq_ctrl_q_init(struct scsc_wifi_fcq_ctrl_q *queue) -{ - return 0; -} - -void scsc_wifi_fcq_ctrl_q_deinit(struct scsc_wifi_fcq_ctrl_q *queue) -{ -} - -int scsc_wifi_fcq_unicast_qset_init(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u8 qs_num, struct slsi_dev *sdev, u8 vif, struct slsi_peer *peer) -{ - return 0; -} - -int scsc_wifi_fcq_multicast_qset_init(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u8 vif) -{ - return 0; -} - -void scsc_wifi_fcq_qset_deinit(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, struct slsi_dev *sdev, u8 vif, struct slsi_peer *peer) -{ -} - -int scsc_wifi_fcq_transmit_data(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - return 0; -} - -int scsc_wifi_fcq_receive_data(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - return 0; -} - -int scsc_wifi_fcq_receive_data_no_peer(struct net_device *dev, u16 priority, struct slsi_dev *sdev, u8 vif, u8 peer_index) -{ - return 0; -} - -void scsc_wifi_fcq_pause_queues(struct slsi_dev *sdev) -{ -} - -void scsc_wifi_fcq_unpause_queues(struct slsi_dev *sdev) -{ -} - -int scsc_wifi_fcq_transmit_ctrl(struct net_device *dev, struct scsc_wifi_fcq_ctrl_q *queue) -{ - return 0; -} - -int scsc_wifi_fcq_receive_ctrl(struct net_device *dev, struct scsc_wifi_fcq_ctrl_q *queue) -{ - return 0; -} - -int scsc_wifi_fcq_update_smod(struct scsc_wifi_fcq_data_qset *qs, enum scsc_wifi_fcq_ps_state peer_ps_state, - enum scsc_wifi_fcq_queue_set_type type) -{ - return 0; -} - -int scsc_wifi_fcq_8021x_port_state(struct net_device *dev, struct scsc_wifi_fcq_data_qset *qs, enum scsc_wifi_fcq_8021x_state state) -{ - return 0; -} - -int scsc_wifi_fcq_stat_queue(struct scsc_wifi_fcq_q_header *queue, - struct scsc_wifi_fcq_q_stat *queue_stat, - int *qmod, int *qcod) -{ - return 0; -} - -int scsc_wifi_fcq_stat_queueset(struct scsc_wifi_fcq_data_qset *queue_set, - struct scsc_wifi_fcq_q_stat *queue_stat, - int *smod, int *scod, enum scsc_wifi_fcq_8021x_state *cp_state, - u32 *peer_ps_state_transitions) -{ - return 0; -} - diff --git a/drivers/net/wireless/scsc/test/hydra_test.c b/drivers/net/wireless/scsc/test/hydra_test.c deleted file mode 100644 index d40d9c92b3bd..000000000000 --- a/drivers/net/wireless/scsc/test/hydra_test.c +++ /dev/null @@ -1,74 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include "dev.h" -#include "unittest.h" -#include "debug.h" -#include "hip_bh.h" - -int slsi_sm_service_driver_register(void) -{ - int csr_result; - - csr_result = slsi_sdio_func_drv_register(); - if (csr_result != 0) { - SLSI_ERR_NODEV("Failed to register the pretend SDIO function driver: csrResult=%d\n", csr_result); - return -EIO; - } - - return 0; -} - -void slsi_sm_service_driver_unregister(void) -{ - slsi_sdio_func_drv_unregister(); -} - -void slsi_sm_service_failed(struct slsi_dev *sdev, const char *reason) -{ -} - -bool slsi_is_test_mode_enabled(void) -{ - return false; -} - -bool slsi_is_rf_test_mode_enabled(void) -{ - return false; -} - -int slsi_check_rf_test_mode(void) -{ - return 0; -} - -int slsi_sm_wlan_service_start(struct slsi_dev *sdev) -{ - return 0; -} - -void slsi_sm_wlan_service_stop(struct slsi_dev *sdev) -{ -} - -int slsi_sm_wlan_service_open(struct slsi_dev *sdev) -{ - return 0; -} - -int mx140_file_request_conf(struct scsc_mx *mx, const struct firmware **conf, const char *config_rel_path, const char *filename) -{ - return 0; -} - -void mx140_file_release_conf(struct scsc_mx *mx, const struct firmware *conf) -{ -} - -void slsi_sm_wlan_service_close(struct slsi_dev *sdev) -{ -} diff --git a/drivers/net/wireless/scsc/test/udi_test.c b/drivers/net/wireless/scsc/test/udi_test.c deleted file mode 100755 index 229fd1d9c1b7..000000000000 --- a/drivers/net/wireless/scsc/test/udi_test.c +++ /dev/null @@ -1,632 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include - -#include "dev.h" - -#include "hip.h" -#include "log_clients.h" -#include "debug.h" -#include "unittest.h" -#include "udi.h" - -#include "unifiio.h" - -#define UDI_CHAR_DEVICE_NAME "s5e7570unittesthip" -#define UDI_CLASS_NAME "s5e7570unittesthip" - -/** - * Control character device for debug - * ================================== - */ -#define NUM_CHAR_CLIENTS 1 /* Number of client programmes on one node. */ - -#define MAX_MINOR (SLSI_UDI_MINOR_NODES - 1) /* Maximum node number. */ -static dev_t major_number; /* Major number of device created by system. */ -static struct class *class; /* Device class. */ - -struct slsi_test_cdev_client; - -struct slsi_cdev { - int minor; - struct cdev cdev; - struct slsi_test_cdev_client *client[NUM_CHAR_CLIENTS]; - - struct slsi_test_dev *uftestdev; - struct device *parent; -}; - -struct slsi_test_cdev_client { - struct slsi_cdev *ufcdev; - int log_enabled; - - /* Flags set for special filtering of ma_packet data */ - u16 ma_packet_filter_config; - - struct sk_buff_head log_list; - wait_queue_head_t log_wq; -}; - -/** - * One minor node per phy. In normal driver mode, this may be one. - * In unit test mode, this may be several. - */ -static struct slsi_cdev *uf_cdevs[SLSI_UDI_MINOR_NODES]; - -static int udi_log_event(struct slsi_log_client *log_client, struct sk_buff *skb, int dir); -static int send_signal_to_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir); -static int send_signal_to_inverse_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir); - -static int slsi_test_cdev_open(struct inode *inode, struct file *file) -{ - struct slsi_cdev *uf_cdev; - struct slsi_test_cdev_client *client; - int indx; - int minor; - - minor = iminor(inode); - if (minor > MAX_MINOR) { - SLSI_ERR_NODEV("minor %d exceeds range\n", minor); - return -EINVAL; - } - - uf_cdev = uf_cdevs[minor]; - if (!uf_cdev) { - SLSI_ERR_NODEV("no cdev instance for minor %d\n", minor); - return -EINVAL; - } - - if (!uf_cdev->uftestdev) { - SLSI_ERR_NODEV("uftestdev not set\n"); - return -EINVAL; - } - - for (indx = 0; indx < NUM_CHAR_CLIENTS; indx++) - if (uf_cdev->client[indx] == NULL) - break; - if (indx >= NUM_CHAR_CLIENTS) { - SLSI_ERR_NODEV("already opened\n"); - return -ENOTSUPP; - } - - client = kmalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memset(client, 0, sizeof(struct slsi_test_cdev_client)); - - /* init other resource */ - skb_queue_head_init(&client->log_list); - init_waitqueue_head(&client->log_wq); - - client->ufcdev = uf_cdev; - uf_cdev->client[indx] = client; - file->private_data = client; - - slsi_test_dev_attach(client->ufcdev->uftestdev); - - return 0; -} - -static int slsi_test_cdev_release(struct inode *inode, struct file *filp) -{ - struct slsi_test_cdev_client *client = (void *)filp->private_data; - struct slsi_cdev *uf_cdev; - int indx; - int minor; - - minor = iminor(inode); - if (minor > MAX_MINOR) { - SLSI_ERR_NODEV("minor %d exceeds range\n", minor); - return -EINVAL; - } - - uf_cdev = uf_cdevs[minor]; - if (!uf_cdev) { - SLSI_ERR_NODEV("no cdev instance for minor %d\n", minor); - return -EINVAL; - } - - if (client == NULL) - return -EINVAL; - - if (!client->ufcdev) { - SLSI_ERR_NODEV("ufcdev not set\n"); - return -EINVAL; - } - - if (!client->ufcdev->uftestdev) { - SLSI_ERR_NODEV("uftestdev not set\n"); - return -EINVAL; - } - - for (indx = 0; indx < NUM_CHAR_CLIENTS; indx++) - if (uf_cdev->client[indx] == client) - break; - if (indx >= NUM_CHAR_CLIENTS) { - SLSI_ERR_NODEV("client not found in list\n"); - return -EINVAL; - } - - if (waitqueue_active(&client->log_wq)) - wake_up_interruptible(&client->log_wq); - - if (client->log_enabled && client->ufcdev->uftestdev->sdev) - slsi_log_client_unregister(client->ufcdev->uftestdev->sdev, client); - - slsi_test_dev_detach(client->ufcdev->uftestdev); - - slsi_skb_queue_purge(&client->log_list); - - /* free other resource */ - kfree(client); - - uf_cdev->client[indx] = NULL; - - return 0; -} - -static ssize_t slsi_test_cdev_read(struct file *filp, char *p, size_t len, loff_t *poff) -{ - struct slsi_test_cdev_client *client = (void *)filp->private_data; - int msglen; - struct sk_buff *skb; - - SLSI_UNUSED_PARAMETER(poff); - - if (client == NULL) - return -EINVAL; - - if (!skb_queue_len(&client->log_list)) { - if (filp->f_flags & O_NONBLOCK) - return 0; - - /* wait until getting a signal */ - if (wait_event_interruptible(client->log_wq, skb_queue_len(&client->log_list))) - return -ERESTARTSYS; - } - - skb = slsi_skb_dequeue(&client->log_list); - - msglen = skb->len; - if (msglen > (s32)len) { - SLSI_WARN_NODEV("truncated read to %d actual msg len is %lu\n", msglen, (unsigned long int)len); - msglen = len; - } - - SLSI_DBG_HEX_NODEV(SLSI_TEST, skb->data, skb->len, "cdev read skb:%p skb->data:%p\n", skb, skb->data); - if (copy_to_user(p, skb->data, msglen)) { - SLSI_ERR_NODEV("Failed to copy UDI log to user\n"); - slsi_kfree_skb(skb); - return -EFAULT; - } - - slsi_kfree_skb(skb); - return msglen; -} - -static ssize_t slsi_test_cdev_write(struct file *filp, const char *p, size_t len, loff_t *poff) -{ - struct slsi_test_cdev_client *client; - struct slsi_test_dev *uftestdev; - struct sk_buff *skb; - struct slsi_skb_cb *cb; - u8 *data; - - SLSI_UNUSED_PARAMETER(poff); - - client = (void *)filp->private_data; - if (client == NULL) { - SLSI_ERR_NODEV("filep private data not set\n"); - return -EINVAL; - } - - if (!client->ufcdev) { - SLSI_ERR_NODEV("ufcdev not set\n"); - return -EINVAL; - } - - uftestdev = client->ufcdev->uftestdev; - if (!uftestdev) { - SLSI_ERR_NODEV("uftestdev not set\n"); - return -EINVAL; - } - - skb = slsi_alloc_skb(len, GFP_KERNEL); - data = skb_put(skb, len); - if (copy_from_user(data, p, len)) { - SLSI_ERR_NODEV("copy from user failed\n"); - slsi_kfree_skb(skb); - return -EFAULT; - } - - if (skb->len < sizeof(struct fapi_signal_header)) { - SLSI_ERR_NODEV("Data(%d) too short for a signal\n", skb->len); - slsi_kfree_skb(skb); - return -EINVAL; - } - - SLSI_DBG_HEX_NODEV(SLSI_TEST, skb->data, skb->len, "cdev write skb:%p skb->data:%p\n", skb, skb->data); - - /* Intercept some requests */ - if (slsi_test_process_signal(uftestdev, skb)) - return len; - - { - struct slsi_dev *sdev; - - sdev = uftestdev->sdev; - if (!sdev) { - SLSI_ERR_NODEV("sdev not set\n"); - slsi_kfree_skb(skb); - return -EINVAL; - } - - cb = slsi_skb_cb_init(skb); - cb->sig_length = fapi_get_expected_size(skb); - cb->data_length = skb->len; - - if (WARN_ON(slsi_hip_rx(sdev, skb))) { - slsi_kfree_skb(skb); - return -EINVAL; - } - } - return len; -} - -static long slsi_test_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct slsi_test_cdev_client *client = (void *)filp->private_data; - struct slsi_test_dev *uftestdev; - struct slsi_dev *sdev; - long r = 0; - int int_param; - - if (client == NULL || client->ufcdev == NULL) - return -EINVAL; - - uftestdev = client->ufcdev->uftestdev; - if (!uftestdev) { - SLSI_ERR_NODEV("uftestdev not set\n"); - return -EINVAL; - } - - sdev = uftestdev->sdev; - if (!sdev) { - SLSI_ERR_NODEV("sdev not set\n"); - return -EINVAL; - } - - FUNC_ENTER_NODEV(); - - slsi_wakelock(&sdev->wlan_wl); - - switch (cmd) { - case UNIFI_GET_UDI_ENABLE: - int_param = client->log_enabled; - put_user(int_param, (int *)arg); - break; - - case UNIFI_SET_UDI_ENABLE: - if (get_user(int_param, (int *)arg)) { - r = -EFAULT; - break; - } - - if (int_param) { - slsi_log_client_register(sdev, client, udi_log_event, NULL, 0, 0); - client->log_enabled = 1; - } else { - slsi_log_client_unregister(sdev, client); - client->log_enabled = 0; - } - - break; - case UNIFI_SET_UDI_LOG_MASK: - { - struct unifiio_filter_t filter; - int i; - - /* to minimise load on data path, list is converted here to array indexed by signal number */ - if (copy_from_user(&filter, (void *)arg, sizeof(filter))) { - SLSI_ERR(sdev, "UNIFI_SET_UDI_LOG_MASK: Failed to copy from userspace\n"); - r = -EFAULT; - break; - } - if (filter.signal_ids_n) { - char *signal_filter_index; - int max; - int min; - int size = filter.signal_ids_n * sizeof(filter.signal_ids[0]); - u16 *signal_ids = kmalloc(size, GFP_KERNEL); - - if (!signal_ids) { - r = -ENOMEM; - break; - } - - max = signal_ids[0]; - min = signal_ids[0]; - - if (copy_from_user(signal_ids, filter.signal_ids, size)) { - SLSI_ERR(sdev, "UNIFI_SET_UDI_LOG_MASK: Failed to copy filter from userspace\n"); - kfree(signal_ids); - r = -EFAULT; - break; - } - /* find maximum and minimum signal id in filter */ - for (i = 0; i < filter.signal_ids_n; i++) { - if (signal_ids[i] & UDI_MA_UNITDATA_FILTER_ALLOW_MASK) { - client->ma_packet_filter_config |= signal_ids[i]; - continue; - } - if (signal_ids[i] > max) - max = signal_ids[i]; - else if (signal_ids[i] < min) - min = signal_ids[i]; - } - /* and create array only big enough to index the range of signal id specified */ - signal_filter_index = kmalloc(max - min + 1, GFP_KERNEL); - if (signal_filter_index) { - memset(signal_filter_index, 0, max - min + 1); - for (i = 0; i < filter.signal_ids_n; i++) { - if (signal_ids[i] & UDI_MA_UNITDATA_FILTER_ALLOW_MASK) - continue; - signal_filter_index[signal_ids[i] - min] = 1; - } - slsi_log_client_unregister(sdev, client); - slsi_log_client_register(sdev, client, - filter.log_listed_flag ? send_signal_to_inverse_log_filter : - send_signal_to_log_filter, signal_filter_index, min, max); - } else { - r = -ENOMEM; - } - kfree(signal_ids); - } - break; - } - default: - SLSI_WARN(sdev, "Operation (%d) not supported\n", cmd); - r = -EINVAL; - } - - slsi_wakeunlock(&sdev->wlan_wl); - return r; -} - -static unsigned int slsi_test_cdev_poll(struct file *filp, poll_table *wait) -{ - struct slsi_test_cdev_client *client = (void *)filp->private_data; - unsigned int mask = 0; - int ready; - - ready = skb_queue_len(&client->log_list); - poll_wait(filp, &client->log_wq, wait); - if (ready) - mask |= POLLIN | POLLRDNORM; /* readable */ - - return mask; -} - -/* we know for sure that there is a filter present in log_client->signal_filter if this function is called. - * we know this because it is called only through a function pointer that is assigned - * only when a filter is also set up in the log_client - */ -static int send_signal_to_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir) -{ - int ret = 0; - u16 signal_id = fapi_get_u16(skb, id); - - if (signal_id > log_client->max_signal_id || signal_id < log_client->min_signal_id || !log_client->signal_filter[signal_id - log_client->min_signal_id]) - ret = udi_log_event(log_client, skb, dir); - - return ret; -} - -static int send_signal_to_inverse_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir) -{ - int ret = 0; - u16 signal_id = fapi_get_u16(skb, id); - - if (signal_id <= log_client->max_signal_id && signal_id >= log_client->min_signal_id && log_client->signal_filter[signal_id - log_client->min_signal_id]) - ret = udi_log_event(log_client, skb, dir); - return ret; -} - -static int udi_log_event(struct slsi_log_client *log_client, struct sk_buff *skb, int dir) -{ - struct slsi_test_cdev_client *client = log_client->log_client_ctx; - struct udi_msg_t msg; - struct udi_msg_t *msg_skb; - - if (WARN_ON(client == NULL)) - return -EINVAL; - if (WARN_ON(skb == NULL)) - return -EINVAL; - if (WARN_ON(skb->len == 0)) - return -EINVAL; - - skb = slsi_skb_copy_expand(skb, sizeof(msg), 0, GFP_ATOMIC); - if (WARN_ON(!skb)) - return -ENOMEM; - - /* Intercept some requests */ - if (slsi_test_process_signal(client->ufcdev->uftestdev, skb)) - return -ECANCELED; - - if (WARN_ON(skb_headroom(skb) < sizeof(msg))) - return -ENOMEM; - - msg.length = sizeof(msg) + skb->len; - msg.timestamp = jiffies_to_msecs(jiffies); - msg.direction = dir; - msg.signal_length = fapi_get_siglen(skb); - - msg_skb = (struct udi_msg_t *)skb_push(skb, sizeof(msg)); - *msg_skb = msg; - - slsi_skb_queue_tail(&client->log_list, skb); - - /* Wake any waiting user process */ - wake_up_interruptible(&client->log_wq); - - return 0; -} - -#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ - device_create(_class, _parent, _devno, _priv, _fmt, _args) - -static const struct file_operations slsi_test_cdev_fops = { - .owner = THIS_MODULE, - .open = slsi_test_cdev_open, - .release = slsi_test_cdev_release, - .read = slsi_test_cdev_read, - .write = slsi_test_cdev_write, - .unlocked_ioctl = slsi_test_cdev_ioctl, - .compat_ioctl = slsi_test_cdev_ioctl, - .poll = slsi_test_cdev_poll, -}; - -#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ - device_create(_class, _parent, _devno, _priv, _fmt, _args) - -static int slsi_get_minor(void) -{ - int minor; - - for (minor = 0; minor < SLSI_UDI_MINOR_NODES; minor++) - if (uf_cdevs[minor] == 0) - return minor; - return -1; -} - -static int slsi_test_cdev_create(struct slsi_test_dev *uftestdev, struct device *parent) -{ - dev_t devno; - int ret; - struct slsi_cdev *pdev; - int minor; - - FUNC_ENTER_NODEV(); - minor = slsi_get_minor(); - if (minor < 0) { - SLSI_ERR_NODEV("no minor numbers available\n"); - return -ENOMEM; - } - - pdev = kmalloc(sizeof(*pdev), GFP_KERNEL); - if (pdev == NULL) - return -ENOMEM; - memset(pdev, 0, sizeof(*pdev)); - - cdev_init(&pdev->cdev, &slsi_test_cdev_fops); - pdev->cdev.owner = THIS_MODULE; - pdev->minor = minor; - devno = MKDEV(MAJOR(major_number), minor); - ret = cdev_add(&pdev->cdev, devno, 1); - if (ret) { - SLSI_ERR_NODEV("cdev_add failed with %d for minor %d\n", ret, minor); - kfree(pdev); - return ret; - } - - pdev->uftestdev = uftestdev; - pdev->parent = parent; - if (!UF_DEVICE_CREATE(class, pdev->parent, devno, pdev, UDI_CHAR_DEVICE_NAME "%d", minor)) { - cdev_del(&pdev->cdev); - kfree(pdev); - return -EINVAL; - } - uftestdev->uf_cdev = (void *)pdev; - uftestdev->device_minor_number = minor; - uf_cdevs[minor] = pdev; - return 0; -} - -static void slsi_test_cdev_destroy(struct slsi_test_dev *uftestdev) -{ - struct slsi_cdev *pdev = (struct slsi_cdev *)uftestdev->uf_cdev; - - FUNC_ENTER_NODEV(); - if (!pdev) - return; - device_destroy(class, pdev->cdev.dev); - cdev_del(&pdev->cdev); - uftestdev->uf_cdev = 0; - uf_cdevs[pdev->minor] = 0; - kfree(pdev); -} - -static int udi_initialised; - -int slsi_test_udi_init(void) -{ - int ret; - - memset(uf_cdevs, 0, sizeof(uf_cdevs)); - - /* Allocate two device numbers for each device. */ - ret = alloc_chrdev_region(&major_number, 0, SLSI_UDI_MINOR_NODES, UDI_CLASS_NAME); - if (ret) { - SLSI_ERR_NODEV("Failed to add alloc dev numbers: %d\n", ret); - return ret; - } - - /* Create a UniFi class */ - class = class_create(THIS_MODULE, UDI_CLASS_NAME); - if (IS_ERR(class)) { - SLSI_ERR_NODEV("Failed to create UniFi class\n"); - unregister_chrdev_region(major_number, SLSI_UDI_MINOR_NODES); - major_number = 0; - return -EINVAL; - } - - udi_initialised = 1; - - return 0; -} - -int slsi_test_udi_deinit(void) -{ - if (!udi_initialised) - return -1; - class_destroy(class); - unregister_chrdev_region(major_number, SLSI_UDI_MINOR_NODES); - udi_initialised = 0; - return 0; -} - -int slsi_test_udi_node_init(struct slsi_test_dev *uftestdev, struct device *parent) -{ - FUNC_ENTER_NODEV(); - if (!udi_initialised) - return -1; - return slsi_test_cdev_create(uftestdev, parent); -} - -int slsi_test_udi_node_reregister(struct slsi_test_dev *uftestdev) -{ - struct slsi_cdev *pdev = uftestdev->uf_cdev; - int indx; - - if (uftestdev->sdev) - for (indx = 0; indx < NUM_CHAR_CLIENTS; indx++) - if (pdev->client[indx] != NULL && pdev->client[indx]->log_enabled) - slsi_log_client_register(uftestdev->sdev, pdev->client[indx], udi_log_event, NULL, 0, 0); - - return 0; -} - -int slsi_test_udi_node_deinit(struct slsi_test_dev *uftestdev) -{ - FUNC_ENTER_NODEV(); - if (!udi_initialised) - return -1; - slsi_test_cdev_destroy(uftestdev); - return 0; -} diff --git a/drivers/net/wireless/scsc/test/unittest.h b/drivers/net/wireless/scsc/test/unittest.h deleted file mode 100755 index e7331c01ea6f..000000000000 --- a/drivers/net/wireless/scsc/test/unittest.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_UNITTEST_H__ -#define __SLSI_UNITTEST_H__ - -#include "dev.h" - -struct slsi_test_dev; -struct slsi_test_bh_work { - bool available; - struct slsi_test_dev *uftestdev; - struct workqueue_struct *workqueue; - struct work_struct work; - struct slsi_spinlock spinlock; -}; - -struct slsi_test_data_route { - bool configured; - u16 test_device_minor_number; /* index into slsi_test_devices[] */ - u8 mac[ETH_ALEN]; - u16 vif; - u8 ipsubnet; - u16 sequence_number; -}; - -struct slsi_test_dev { - /* This is used for: - * 1) The uf6kunittesthip chardevice number - * 2) The uf6kunittest chardevice number - * 3) The /procf/devices/unifi number - */ - int device_minor_number; - - void *uf_cdev; - struct device *dev; - struct slsi_dev *sdev; - - struct workqueue_struct *attach_detach_work_queue; - /* a std mutex */ - struct mutex attach_detach_mutex; - struct work_struct attach_work; - struct work_struct detach_work; - bool attached; - - u8 hw_addr[ETH_ALEN]; - struct slsi_test_bh_work bh_work; - - /* a std spinlock */ - spinlock_t route_spinlock; - struct slsi_test_data_route route[SLSI_AP_PEER_CONNECTIONS_MAX]; -}; - -void slsi_test_dev_attach(struct slsi_test_dev *uftestdev); -void slsi_test_dev_detach(struct slsi_test_dev *uftestdev); -bool slsi_test_process_signal(struct slsi_test_dev *uftestdev, struct sk_buff *skb); - -int slsi_test_udi_node_init(struct slsi_test_dev *uftestdev, struct device *parent); -int slsi_test_udi_node_reregister(struct slsi_test_dev *uftestdev); -int slsi_test_udi_node_deinit(struct slsi_test_dev *uftestdev); - -int slsi_test_udi_init(void); -int slsi_test_udi_deinit(void); - -void slsi_test_bh_work_f(struct work_struct *work); -static inline int slsi_test_bh_init(struct slsi_test_dev *uftestdev) -{ - uftestdev->bh_work.available = false; - uftestdev->bh_work.uftestdev = uftestdev; - slsi_spinlock_create(&uftestdev->bh_work.spinlock); - INIT_WORK(&uftestdev->bh_work.work, slsi_test_bh_work_f); - uftestdev->bh_work.workqueue = alloc_ordered_workqueue("slsi_wlan_unittest_bh", 0); - if (!uftestdev->bh_work.workqueue) - return -ENOMEM; - uftestdev->bh_work.available = true; - return 0; -} - -static inline void slsi_test_bh_start(struct slsi_test_dev *uftestdev) -{ - slsi_spinlock_lock(&uftestdev->bh_work.spinlock); - uftestdev->bh_work.available = true; - slsi_spinlock_unlock(&uftestdev->bh_work.spinlock); -} - -static inline void slsi_test_bh_run(struct slsi_test_dev *uftestdev) -{ - slsi_spinlock_lock(&uftestdev->bh_work.spinlock); - if (!uftestdev->bh_work.available) - goto exit; - queue_work(uftestdev->bh_work.workqueue, &uftestdev->bh_work.work); -exit: - slsi_spinlock_unlock(&uftestdev->bh_work.spinlock); -} - -static inline void slsi_test_bh_stop(struct slsi_test_dev *uftestdev) -{ - struct workqueue_struct *workqueue = NULL; - - slsi_spinlock_lock(&uftestdev->bh_work.spinlock); - uftestdev->bh_work.available = false; - workqueue = uftestdev->bh_work.workqueue; - uftestdev->bh_work.workqueue = NULL; - slsi_spinlock_unlock(&uftestdev->bh_work.spinlock); - - if (workqueue) - flush_workqueue(workqueue); -} - -static inline void slsi_test_bh_deinit(struct slsi_test_dev *uftestdev) -{ - struct workqueue_struct *workqueue = NULL; - - slsi_spinlock_lock(&uftestdev->bh_work.spinlock); - WARN_ON(uftestdev->bh_work.available); - uftestdev->bh_work.available = false; - workqueue = uftestdev->bh_work.workqueue; - uftestdev->bh_work.workqueue = NULL; - slsi_spinlock_unlock(&uftestdev->bh_work.spinlock); - if (workqueue) { - flush_workqueue(workqueue); - destroy_workqueue(workqueue); - } -} - -#endif diff --git a/drivers/net/wireless/scsc/traffic_monitor.c b/drivers/net/wireless/scsc/traffic_monitor.c deleted file mode 100644 index 8913a623d2c0..000000000000 --- a/drivers/net/wireless/scsc/traffic_monitor.c +++ /dev/null @@ -1,330 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ -#include -#include "dev.h" -#include "debug.h" -#include "traffic_monitor.h" - -struct slsi_traffic_mon_client_entry { - struct list_head q; - void *client_ctx; - u32 throughput; - u32 state; - u32 hysteresis; - u32 mode; - u32 mid_tput; - u32 high_tput; - void (*traffic_mon_client_cb)(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx); -}; - -static inline void traffic_mon_invoke_client_callback(struct slsi_dev *sdev, u32 tput_tx, u32 tput_rx) -{ - struct list_head *pos, *n; - struct slsi_traffic_mon_client_entry *traffic_client; - - list_for_each_safe(pos, n, &sdev->traffic_mon_clients.client_list) { - traffic_client = list_entry(pos, struct slsi_traffic_mon_client_entry, q); - - if (traffic_client->mode == TRAFFIC_MON_CLIENT_MODE_PERIODIC) { - if (traffic_client->traffic_mon_client_cb) - traffic_client->traffic_mon_client_cb(traffic_client->client_ctx, TRAFFIC_MON_CLIENT_STATE_NONE, tput_tx, tput_rx); - } else if (traffic_client->mode == TRAFFIC_MON_CLIENT_MODE_EVENTS) { - if ((traffic_client->high_tput) && ((tput_tx + tput_rx) > traffic_client->high_tput)) { - if (traffic_client->state != TRAFFIC_MON_CLIENT_STATE_HIGH && - (traffic_client->hysteresis++ > SLSI_TRAFFIC_MON_HYSTERESIS_HIGH)) { - SLSI_DBG1(sdev, SLSI_HIP, "notify traffic event (tput:%u, state:%u --> HIGH)\n", (tput_tx + tput_rx), traffic_client->state); - traffic_client->hysteresis = 0; - traffic_client->state = TRAFFIC_MON_CLIENT_STATE_HIGH; - - if (traffic_client->traffic_mon_client_cb) - traffic_client->traffic_mon_client_cb(traffic_client->client_ctx, TRAFFIC_MON_CLIENT_STATE_HIGH, tput_tx, tput_rx); - } - } else if ((traffic_client->mid_tput) && ((tput_tx + tput_rx) > traffic_client->mid_tput)) { - if (traffic_client->state != TRAFFIC_MON_CLIENT_STATE_MID) { - if ((traffic_client->state == TRAFFIC_MON_CLIENT_STATE_LOW && (traffic_client->hysteresis++ > SLSI_TRAFFIC_MON_HYSTERESIS_HIGH)) || - (traffic_client->state == TRAFFIC_MON_CLIENT_STATE_HIGH && (traffic_client->hysteresis++ > SLSI_TRAFFIC_MON_HYSTERESIS_LOW))) { - SLSI_DBG1(sdev, SLSI_HIP, "notify traffic event (tput:%u, state:%u --> MID)\n", (tput_tx + tput_rx), traffic_client->state); - traffic_client->hysteresis = 0; - traffic_client->state = TRAFFIC_MON_CLIENT_STATE_MID; - if (traffic_client->traffic_mon_client_cb) - traffic_client->traffic_mon_client_cb(traffic_client->client_ctx, TRAFFIC_MON_CLIENT_STATE_MID, tput_tx, tput_rx); - } - } - } else if (traffic_client->state != TRAFFIC_MON_CLIENT_STATE_LOW && - (traffic_client->hysteresis++ > SLSI_TRAFFIC_MON_HYSTERESIS_LOW)) { - SLSI_DBG1(sdev, SLSI_HIP, "notify traffic event (tput:%u, state:%u --> LOW\n", (tput_tx + tput_rx), traffic_client->state); - traffic_client->hysteresis = 0; - traffic_client->state = TRAFFIC_MON_CLIENT_STATE_LOW; - if (traffic_client->traffic_mon_client_cb) - traffic_client->traffic_mon_client_cb(traffic_client->client_ctx, TRAFFIC_MON_CLIENT_STATE_LOW, tput_tx, tput_rx); - } - } - traffic_client->throughput = (tput_tx + tput_rx); - } -} - -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE -static void traffic_mon_timer(struct timer_list *t) -#else -static void traffic_mon_timer(unsigned long data) -#endif -{ -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - struct slsi_traffic_mon_clients *clients = from_timer(clients, t, timer); - struct slsi_dev *sdev = container_of(clients, typeof(*sdev), traffic_mon_clients); -#else - struct slsi_dev *sdev = (struct slsi_dev *)data; -#endif - struct net_device *dev; - struct netdev_vif *ndev_vif; - bool stop_monitor; - u8 i; - u32 tput_rx = 0; - u32 tput_tx = 0; - - if (!sdev) { - SLSI_ERR_NODEV("invalid sdev\n"); - return; - } - - spin_lock_bh(&sdev->traffic_mon_clients.lock); - - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) { - dev = sdev->netdev[i]; - if (dev) { - ndev_vif = netdev_priv(dev); - - if (ndev_vif) { - u32 time_in_ms = 0; - - /* the Timer is jiffies based so resolution is not High and it may - * be off by a few ms. So to accurately measure the throughput find - * the time diff between last timer and this one - */ - time_in_ms = ktime_to_ms(ktime_sub(ktime_get(), ndev_vif->last_timer_time)); - - /* the Timer may be any value but it still needs to calculate the - * throughput over a period of 1 second - */ - ndev_vif->num_bytes_rx_per_sec += ndev_vif->num_bytes_rx_per_timer; - ndev_vif->num_bytes_tx_per_sec += ndev_vif->num_bytes_tx_per_timer; - ndev_vif->report_time += time_in_ms; - if (ndev_vif->report_time >= 1000) { - ndev_vif->throughput_rx_bps = (ndev_vif->num_bytes_rx_per_sec * 8 / ndev_vif->report_time) * 1000; - ndev_vif->throughput_tx_bps = (ndev_vif->num_bytes_tx_per_sec * 8 / ndev_vif->report_time) * 1000; - ndev_vif->num_bytes_rx_per_sec = 0; - ndev_vif->num_bytes_tx_per_sec = 0; - ndev_vif->report_time = 0; - } - - /* throughput per timer interval is measured but extrapolated to 1 sec */ - ndev_vif->throughput_tx = (ndev_vif->num_bytes_tx_per_timer * 8 / time_in_ms) * 1000; - ndev_vif->throughput_rx = (ndev_vif->num_bytes_rx_per_timer * 8 / time_in_ms) * 1000; - - ndev_vif->num_bytes_tx_per_timer = 0; - ndev_vif->num_bytes_rx_per_timer = 0; - ndev_vif->last_timer_time = ktime_get(); - tput_tx += ndev_vif->throughput_tx; - tput_rx += ndev_vif->throughput_rx; - } - } - } - - traffic_mon_invoke_client_callback(sdev, tput_tx, tput_rx); - stop_monitor = list_empty(&sdev->traffic_mon_clients.client_list); - - spin_unlock_bh(&sdev->traffic_mon_clients.lock); - if (!stop_monitor) - mod_timer(&sdev->traffic_mon_clients.timer, jiffies + msecs_to_jiffies(SLSI_TRAFFIC_MON_TIMER_PERIOD)); -} - -inline void slsi_traffic_mon_event_rx(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - - /* Apply a correction to length to exclude IP and transport header. - * Can either peek into packets to derive the exact payload size - * or apply a rough correction to roughly calculate the throughput. - * rough correction is applied with a number inbetween IP header (20 bytes) + - * UDP header (8 bytes) or TCP header (can be 20 bytes to 60 bytes) i.e. 40 - */ - if (skb->len >= 40) - ndev_vif->num_bytes_rx_per_timer += (skb->len - 40); - else - ndev_vif->num_bytes_rx_per_timer += skb->len; -} - -inline void slsi_traffic_mon_event_tx(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_skb_cb *cb = slsi_skb_cb_get(skb); - - if ((skb->len - cb->sig_length) >= 40) - ndev_vif->num_bytes_tx_per_timer += ((skb->len - 40) - cb->sig_length); - else - ndev_vif->num_bytes_tx_per_timer += (skb->len - cb->sig_length); -} - -u8 slsi_traffic_mon_is_running(struct slsi_dev *sdev) -{ - u8 is_running = 0; - - spin_lock_bh(&sdev->traffic_mon_clients.lock); - if (!list_empty(&sdev->traffic_mon_clients.client_list)) - is_running = 1; - spin_unlock_bh(&sdev->traffic_mon_clients.lock); - return is_running; -} - -int slsi_traffic_mon_client_register( - struct slsi_dev *sdev, - void *client_ctx, - u32 mode, - u32 mid_tput, - u32 high_tput, - void (*traffic_mon_client_cb)(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx)) -{ - struct slsi_traffic_mon_client_entry *traffic_mon_client; - bool start_monitor; - struct net_device *dev; - struct netdev_vif *ndev_vif; - u8 i; - - if (!client_ctx) { - SLSI_ERR(sdev, "A client context must be provided\n"); - return -EINVAL; - } - - spin_lock_bh(&sdev->traffic_mon_clients.lock); - SLSI_DBG1(sdev, SLSI_HIP, "client:%p, mode:%u, mid_tput:%u, high_tput:%u\n", client_ctx, mode, mid_tput, high_tput); - start_monitor = list_empty(&sdev->traffic_mon_clients.client_list); - traffic_mon_client = kmalloc(sizeof(*traffic_mon_client), GFP_ATOMIC); - if (!traffic_mon_client) { - SLSI_ERR(sdev, "could not allocate memory for Monitor client\n"); - spin_unlock_bh(&sdev->traffic_mon_clients.lock); - return -ENOMEM; - } - - traffic_mon_client->client_ctx = client_ctx; - traffic_mon_client->state = TRAFFIC_MON_CLIENT_STATE_LOW; - traffic_mon_client->hysteresis = 0; - traffic_mon_client->mode = mode; - traffic_mon_client->mid_tput = mid_tput; - traffic_mon_client->high_tput = high_tput; - traffic_mon_client->traffic_mon_client_cb = traffic_mon_client_cb; - - /* Add to tail of monitor clients queue */ - list_add_tail(&traffic_mon_client->q, &sdev->traffic_mon_clients.client_list); - - if (start_monitor) { - /* reset counters before starting Timer */ - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) { - dev = sdev->netdev[i]; - if (dev) { - ndev_vif = netdev_priv(dev); - - if (ndev_vif) { - ndev_vif->throughput_tx = 0; - ndev_vif->throughput_rx = 0; - ndev_vif->num_bytes_tx_per_timer = 0; - ndev_vif->num_bytes_rx_per_timer = 0; - ndev_vif->last_timer_time = ktime_get(); - ndev_vif->num_bytes_rx_per_sec = 0; - ndev_vif->num_bytes_tx_per_sec = 0; - ndev_vif->throughput_rx_bps = 0; - ndev_vif->throughput_tx_bps = 0; - ndev_vif->report_time = 0; - } - } - } - mod_timer(&sdev->traffic_mon_clients.timer, jiffies + msecs_to_jiffies(SLSI_TRAFFIC_MON_TIMER_PERIOD)); - } - - spin_unlock_bh(&sdev->traffic_mon_clients.lock); - return 0; -} - -void slsi_traffic_mon_client_unregister(struct slsi_dev *sdev, void *client_ctx) -{ - struct list_head *pos, *n; - struct slsi_traffic_mon_client_entry *traffic_mon_client; - struct net_device *dev; - struct netdev_vif *ndev_vif; - u8 i; - - spin_lock_bh(&sdev->traffic_mon_clients.lock); - SLSI_DBG1(sdev, SLSI_HIP, "client: %p\n", client_ctx); - list_for_each_safe(pos, n, &sdev->traffic_mon_clients.client_list) { - traffic_mon_client = list_entry(pos, struct slsi_traffic_mon_client_entry, q); - if (traffic_mon_client->client_ctx == client_ctx) { - SLSI_DBG1(sdev, SLSI_HIP, "delete: %p\n", traffic_mon_client->client_ctx); - list_del(pos); - kfree(traffic_mon_client); - } - } - - if (list_empty(&sdev->traffic_mon_clients.client_list)) { - /* reset counters */ - for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) { - dev = sdev->netdev[i]; - if (dev) { - ndev_vif = netdev_priv(dev); - - if (ndev_vif) { - ndev_vif->throughput_tx = 0; - ndev_vif->throughput_rx = 0; - ndev_vif->num_bytes_tx_per_timer = 0; - ndev_vif->num_bytes_rx_per_timer = 0; - ndev_vif->num_bytes_rx_per_sec = 0; - ndev_vif->num_bytes_tx_per_sec = 0; - ndev_vif->throughput_rx_bps = 0; - ndev_vif->throughput_tx_bps = 0; - ndev_vif->report_time = 0; - } - } - } - spin_unlock_bh(&sdev->traffic_mon_clients.lock); - del_timer_sync(&sdev->traffic_mon_clients.timer); - spin_lock_bh(&sdev->traffic_mon_clients.lock); - } - spin_unlock_bh(&sdev->traffic_mon_clients.lock); -} - -void slsi_traffic_mon_clients_init(struct slsi_dev *sdev) -{ - if (!sdev) { - SLSI_ERR_NODEV("invalid sdev\n"); - return; - } -#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE - timer_setup(&sdev->traffic_mon_clients.timer, traffic_mon_timer, 0); -#else - setup_timer(&sdev->traffic_mon_clients.timer, traffic_mon_timer, (unsigned long)sdev); -#endif - INIT_LIST_HEAD(&sdev->traffic_mon_clients.client_list); - spin_lock_init(&sdev->traffic_mon_clients.lock); -} - -void slsi_traffic_mon_clients_deinit(struct slsi_dev *sdev) -{ - struct list_head *pos, *n; - struct slsi_traffic_mon_client_entry *traffic_mon_client; - - if (!sdev) { - SLSI_ERR_NODEV("invalid sdev\n"); - return; - } - - spin_lock_bh(&sdev->traffic_mon_clients.lock); - list_for_each_safe(pos, n, &sdev->traffic_mon_clients.client_list) { - traffic_mon_client = list_entry(pos, struct slsi_traffic_mon_client_entry, q); - SLSI_DBG1(sdev, SLSI_HIP, "delete: %p\n", traffic_mon_client->client_ctx); - list_del(pos); - kfree(traffic_mon_client); - } - spin_unlock_bh(&sdev->traffic_mon_clients.lock); - del_timer_sync(&sdev->traffic_mon_clients.timer); -} diff --git a/drivers/net/wireless/scsc/traffic_monitor.h b/drivers/net/wireless/scsc/traffic_monitor.h deleted file mode 100644 index 21e9f4d2e650..000000000000 --- a/drivers/net/wireless/scsc/traffic_monitor.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __TRAFFIC_MONITOR_H__ -#define __TRAFFIC_MONITOR_H__ - -#define SLSI_TRAFFIC_MON_TIMER_PERIOD 100 /* in ms */ -#define SLSI_TRAFFIC_MON_HYSTERESIS_HIGH 2 /* in number of timer period */ -#define SLSI_TRAFFIC_MON_HYSTERESIS_LOW 10 /* in number of timer period */ - -enum { - TRAFFIC_MON_CLIENT_MODE_NONE, - TRAFFIC_MON_CLIENT_MODE_PERIODIC, - TRAFFIC_MON_CLIENT_MODE_EVENTS -}; - -enum { - TRAFFIC_MON_CLIENT_STATE_NONE, - TRAFFIC_MON_CLIENT_STATE_LOW, - TRAFFIC_MON_CLIENT_STATE_MID, - TRAFFIC_MON_CLIENT_STATE_HIGH -}; - -struct slsi_traffic_mon_clients { - /* client list lock */ - spinlock_t lock; - - struct timer_list timer; - struct list_head client_list; -}; - -void slsi_traffic_mon_event_rx(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_traffic_mon_event_tx(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); - -/* Is traffic monitor running? - * - * A caller can seek whether the traffic monitor is running or not. - * If the traffic monitor is running, then the throughput for Rx and - * Tx is stored in netdev_vif structure and caller can access them. - * - * Returns: 1 - traffic monitor is running - * 0 - traffic monitor is NOT running - */ -u8 slsi_traffic_mon_is_running(struct slsi_dev *sdev); - -/* register a client to traffic monitor - * - * A client can register to traffic monitor to either get notification - * per timer period or to get notification when the throughput changes - * state from one state of LOW/MID/HIGH to another. - * - * client_ctx: client context that is passed back in callback - * Also, is an unique ID for the client. - * mode: can be periodic or event based - * mid_tput: Mid throughput level - * high_tput: High throughput level - * traffic_mon_client_cb: function to callback each period or on events - * This function is called back in Timer interrupt - * context. - */ -int slsi_traffic_mon_client_register( - struct slsi_dev *sdev, - void *client_ctx, - u32 mode, - u32 mid_tput, - u32 high_tput, - /* WARNING: THIS IS CALLED BACK IN TIMER INTERRUPT CONTEXT! */ - void (*traffic_mon_client_cb)(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx)); -void slsi_traffic_mon_client_unregister(struct slsi_dev *sdev, void *client_ctx); - -void slsi_traffic_mon_clients_init(struct slsi_dev *sdev); -void slsi_traffic_mon_clients_deinit(struct slsi_dev *sdev); - -#endif diff --git a/drivers/net/wireless/scsc/tx.c b/drivers/net/wireless/scsc/tx.c deleted file mode 100755 index c8236ee3e51b..000000000000 --- a/drivers/net/wireless/scsc/tx.c +++ /dev/null @@ -1,626 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#include "dev.h" -#include "debug.h" -#include "mgt.h" -#include "mlme.h" -#include "netif.h" -#include "log_clients.h" -#include "hip4_sampler.h" -#include "traffic_monitor.h" - -static bool msdu_enable = true; -module_param(msdu_enable, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(msdu_enable, "MSDU frame format, Y: enable (default), N: disable"); - -#ifdef CONFIG_ANDROID -#include "scsc_wifilogger_rings.h" -#endif - -/** - * Needed to get HIP4_DAT)SLOTS...should be part - * of initialization and callbacks registering - */ -#include "hip4.h" - -#include - -int slsi_get_dwell_time_for_wps(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, u8 *eapol, u16 eap_length) -{ - /* Note that Message should not be M8.This check is to identify only WSC_START message or M1-M7 */ - /*Return 100ms If opcode type WSC msg and Msg Type M1-M7 or if opcode is WSC start.*/ - if (eapol[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_REQUEST || - eapol[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_RESPONSE) { - if (eapol[SLSI_EAP_TYPE_POS] == SLSI_EAP_TYPE_EXPANDED && eap_length >= SLSI_EAP_OPCODE_POS - 3 && - ((eapol[SLSI_EAP_OPCODE_POS] == SLSI_EAP_OPCODE_WSC_MSG && eap_length >= SLSI_EAP_MSGTYPE_POS - 3 && - eapol[SLSI_EAP_MSGTYPE_POS] != SLSI_EAP_MSGTYPE_M8) || - eapol[SLSI_EAP_OPCODE_POS] == SLSI_EAP_OPCODE_WSC_START)) - return SLSI_EAP_WPS_DWELL_TIME; - /* This is to check if a frame is EAP request identity and on P2P vif.If yes then set dwell time to 100ms */ - if (SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif) && - eapol[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_REQUEST && - eapol[SLSI_EAP_TYPE_POS] == SLSI_EAP_TYPE_IDENTITY) - return SLSI_EAP_WPS_DWELL_TIME; - } - return 0; -} - -static int slsi_tx_eapol(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - u8 *eapol = NULL; - u16 msg_type = 0; - u16 proto = ntohs(skb->protocol); - int ret = 0; - u32 dwell_time = sdev->fw_dwell_time; - u64 tx_bytes_tmp = 0; - u16 eap_length = 0; - - slsi_spinlock_lock(&ndev_vif->peer_lock); - peer = slsi_get_peer_from_mac(sdev, dev, eth_hdr(skb)->h_dest); - if (!peer) { - slsi_spinlock_unlock(&ndev_vif->peer_lock); - SLSI_NET_WARN(dev, "no peer record for %pM, drop EAP frame\n", eth_hdr(skb)->h_dest); - return -EINVAL; - } - - switch (proto) { - case ETH_P_PAE: - /* Detect if this is an EAPOL key frame. If so detect if - * it is an EAPOL-Key M4 packet - * In M4 packet, - * - MIC bit set in key info - * - Key type bit set in key info (pairwise=1, Group=0) - * - ACK bit will not be set - * - Secure bit will be set in key type RSN (WPA2/WPA3 Personal/WPA3 Enterprise) - * - Key Data length check for Zero is for WPA as Secure bit will not be set - */ - if ((skb->len - sizeof(struct ethhdr)) >= 99) - eapol = skb->data + sizeof(struct ethhdr); - if (eapol && eapol[SLSI_EAPOL_IEEE8021X_TYPE_POS] == SLSI_IEEE8021X_TYPE_EAPOL_KEY) { - msg_type = FAPI_MESSAGETYPE_EAPOL_KEY_M123; - - if ((eapol[SLSI_EAPOL_TYPE_POS] == SLSI_EAPOL_TYPE_RSN_KEY || eapol[SLSI_EAPOL_TYPE_POS] == SLSI_EAPOL_TYPE_WPA_KEY) && - (eapol[SLSI_EAPOL_KEY_INFO_LOWER_BYTE_POS] & SLSI_EAPOL_KEY_INFO_KEY_TYPE_BIT_IN_LOWER_BYTE) && - (!(eapol[SLSI_EAPOL_KEY_INFO_LOWER_BYTE_POS] & SLSI_EAPOL_KEY_INFO_ACK_BIT_IN_LOWER_BYTE)) && - (eapol[SLSI_EAPOL_KEY_INFO_HIGHER_BYTE_POS] & SLSI_EAPOL_KEY_INFO_MIC_BIT_IN_HIGHER_BYTE) && - ((eapol[SLSI_EAPOL_KEY_INFO_HIGHER_BYTE_POS] & SLSI_EAPOL_KEY_INFO_SECURE_BIT_IN_HIGHER_BYTE) || - ((eapol[SLSI_EAPOL_KEY_DATA_LENGTH_HIGHER_BYTE_POS] == 0) && (eapol[SLSI_EAPOL_KEY_DATA_LENGTH_LOWER_BYTE_POS] == 0)))) { - msg_type = FAPI_MESSAGETYPE_EAPOL_KEY_M4; - dwell_time = 0; - } - } else { - msg_type = FAPI_MESSAGETYPE_EAP_MESSAGE; - if ((skb->len - sizeof(struct ethhdr)) >= 9) - eapol = skb->data + sizeof(struct ethhdr); - - dwell_time = 0; - if (eapol && eapol[SLSI_EAPOL_IEEE8021X_TYPE_POS] == SLSI_IEEE8021X_TYPE_EAP_PACKET) { - eap_length = (skb->len - sizeof(struct ethhdr)) - 4; - if (eapol[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_REQUEST) - SLSI_INFO(sdev, "Send EAP-Request (%d)\n", eap_length); - else if (eapol[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_RESPONSE) - SLSI_INFO(sdev, "Send EAP-Response (%d)\n", eap_length); - else if (eapol[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_SUCCESS) - SLSI_INFO(sdev, "Send EAP-Success (%d)\n", eap_length); - else if (eapol[SLSI_EAP_CODE_POS] == SLSI_EAP_PACKET_FAILURE) - SLSI_INFO(sdev, "Send EAP-Failure (%d)\n", eap_length); - /* Need to set dwell time for wps exchange and EAP identity frame for P2P */ - dwell_time = slsi_get_dwell_time_for_wps(sdev, ndev_vif, eapol, eap_length); - } - } - break; - case ETH_P_WAI: - SLSI_NET_DBG1(dev, SLSI_MLME, "WAI protocol frame\n"); - msg_type = FAPI_MESSAGETYPE_WAI_MESSAGE; - if ((skb->data[17]) != 9) /*subtype 9 refers to unicast negotiation response*/ - dwell_time = 0; - break; - default: - SLSI_NET_WARN(dev, "protocol NOT supported\n"); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return -EOPNOTSUPP; - } - - /* EAPOL/WAI frames are send via the MLME */ - tx_bytes_tmp = skb->len; /*len copy to avoid null pointer of skb*/ - ret = slsi_mlme_send_frame_data(sdev, dev, skb, msg_type, 0, dwell_time, 0); - if (!ret) - peer->sinfo.tx_bytes += tx_bytes_tmp; //skb->len; - - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return ret; -} - -uint slsi_sg_host_align_mask; /* TODO -- this needs to be resolved! */ - -/** - * This function deals with TX of data frames. - * On success, skbs are properly FREED; on error skb is NO MORE freed. - * - * NOTE THAT currently ONLY the following set of err-codes will trigger - * a REQUEUE and RETRY by upper layers in Kernel NetStack: - * - * -ENOSPC - */ -int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct slsi_skb_cb *cb; - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct slsi_peer *peer; - struct sk_buff *original_skb = NULL; - u16 len = skb->len; - int ret = 0; - enum slsi_traffic_q tq; - u32 dwell_time = 0; - u8 *frame; - u16 arp_opcode; - u32 dhcp_message_type = SLSI_DHCP_MESSAGE_TYPE_INVALID; - - if (slsi_is_test_mode_enabled()) { - /* This signals is in XML file because parts of the Firmware need the symbols defined by them - * but this is actually not handled in wlanlite firmware. - */ - SLSI_NET_WARN(dev, "WlanLite: NOT supported\n"); - return -EOPNOTSUPP; - } - - if (!ndev_vif->activated) { - SLSI_NET_WARN(dev, "vif NOT activated\n"); - return -EINVAL; - } - - if ((ndev_vif->vif_type == FAPI_VIFTYPE_AP) && !ndev_vif->peer_sta_records) { - SLSI_NET_DBG3(dev, SLSI_TX, "AP with no STAs associated, drop Tx frame\n"); - return -EINVAL; - } - - /* check if it is an high important frame? At the moment EAPOL, DHCP - * and ARP are treated as high important frame and are sent over - * MLME for applying special rules in transmission. - */ - if (skb->queue_mapping == SLSI_NETIF_Q_PRIORITY) { - int proto = be16_to_cpu(eth_hdr(skb)->h_proto); - - switch (proto) { - default: - /* Only EAP packets and IP frames with DHCP are stored in SLSI_NETIF_Q_PRIORITY */ - SLSI_NET_ERR(dev, "Bad h_proto=0x%x in SLSI_NETIF_Q_PRIORITY\n", proto); - return -EINVAL; - case ETH_P_PAE: - case ETH_P_WAI: - SLSI_NET_DBG2(dev, SLSI_MLME, "transmit EAP packet from SLSI_NETIF_Q_PRIORITY\n"); - return slsi_tx_eapol(sdev, dev, skb); - case ETH_P_ARP: - SLSI_NET_DBG2(dev, SLSI_MLME, "transmit ARP frame from SLSI_NETIF_Q_PRIORITY\n"); - frame = skb->data + sizeof(struct ethhdr); - arp_opcode = frame[SLSI_ARP_OPCODE_OFFSET] << 8 | frame[SLSI_ARP_OPCODE_OFFSET + 1]; - if ((arp_opcode == SLSI_ARP_REQUEST_OPCODE) && - !SLSI_IS_GRATUITOUS_ARP(frame)) { -#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT - if (ndev_vif->enhanced_arp_detect_enabled && - !memcmp(&frame[SLSI_ARP_DEST_IP_ADDR_OFFSET], &ndev_vif->target_ip_addr, 4)) { - ndev_vif->enhanced_arp_stats.arp_req_count_from_netdev++; - } -#endif - dwell_time = sdev->fw_dwell_time; - } - return slsi_mlme_send_frame_data(sdev, dev, skb, FAPI_MESSAGETYPE_ARP, 0, dwell_time, 0); - case ETH_P_IP: - if (skb->len >= 285 && slsi_is_dhcp_packet(skb->data) != SLSI_TX_IS_NOT_DHCP) { - if (skb->data[42] == 1) /*opcode 1 refers to DHCP discover/request*/ - dwell_time = sdev->fw_dwell_time; - dhcp_message_type = skb->data[284]; - if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_DISCOVER) - SLSI_INFO(sdev, "Send DHCP [DISCOVER]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_OFFER) - SLSI_INFO(sdev, "Send DHCP [OFFER]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_REQUEST) - SLSI_INFO(sdev, "Send DHCP [REQUEST]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_DECLINE) - SLSI_INFO(sdev, "Send DHCP [DECLINE]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_ACK) - SLSI_INFO(sdev, "Send DHCP [ACK]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_NAK) - SLSI_INFO(sdev, "Send DHCP [NAK]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_RELEASE) - SLSI_INFO(sdev, "Send DHCP [RELEASE]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_INFORM) - SLSI_INFO(sdev, "Send DHCP [INFORM]\n"); - else if (dhcp_message_type == SLSI_DHCP_MESSAGE_TYPE_FORCERENEW) - SLSI_INFO(sdev, "Send DHCP [FORCERENEW]\n"); - else - SLSI_INFO(sdev, "Send DHCP [INVALID]\n"); - return slsi_mlme_send_frame_data(sdev, dev, skb, FAPI_MESSAGETYPE_DHCP, 0, dwell_time, - 0); - } - /* IP frame can have only DHCP packet in SLSI_NETIF_Q_PRIORITY */ - SLSI_NET_ERR(dev, "Bad IP frame in SLSI_NETIF_Q_PRIORITY\n"); - return -EINVAL; - } - } - - if (skb_headroom(skb) < (fapi_sig_size(ma_unitdata_req) + 160)) { - struct sk_buff *skb2 = NULL; - - skb2 = slsi_skb_realloc_headroom(skb, fapi_sig_size(ma_unitdata_req) + 160); - if (!skb2) { - SLSI_NET_WARN(dev, "failed to alloc SKB headroom, drop Tx frame\n"); - return -EINVAL; - } - /* Keep track of this copy...*/ - original_skb = skb; - skb = skb2; - } - - /* Align mac_header with skb->data */ - if (skb_headroom(skb) != skb->mac_header) - skb_pull(skb, skb->mac_header - skb_headroom(skb)); - - if (msdu_enable) - ethr_ii_to_subframe_msdu(skb); - - len = skb->len; - - (void)skb_push(skb, fapi_sig_size(ma_unitdata_req)); - tq = slsi_frame_priority_to_ac_queue(skb->priority); - fapi_set_u16(skb, id, MA_UNITDATA_REQ); - fapi_set_u16(skb, receiver_pid, 0); - fapi_set_u16(skb, sender_pid, SLSI_TX_PROCESS_ID_MIN); - fapi_set_u32(skb, fw_reference, 0); - fapi_set_u16(skb, u.ma_unitdata_req.vif, ndev_vif->ifnum); - fapi_set_u16(skb, u.ma_unitdata_req.host_tag, slsi_tx_host_tag(sdev, tq)); - fapi_set_u16(skb, u.ma_unitdata_req.peer_index, MAP_QS_TO_AID(slsi_netif_get_qs_from_queue - (skb->queue_mapping, tq))); - - SCSC_HIP4_SAMPLER_PKT_TX(sdev->minor_prof, fapi_get_u16(skb, u.ma_unitdata_req.host_tag)); - - /* by default the priority is set to contention. It is overridden and set appropriate - * priority if peer supports QoS. The broadcast/multicast frames are sent in non-QoS . - */ - fapi_set_u16(skb, u.ma_unitdata_req.priority, FAPI_PRIORITY_CONTENTION); - - if (msdu_enable) - fapi_set_u16(skb, u.ma_unitdata_req.data_unit_descriptor, FAPI_DATAUNITDESCRIPTOR_AMSDU_SUBFRAME); - else - fapi_set_u16(skb, u.ma_unitdata_req.data_unit_descriptor, FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME); - - SLSI_NET_DBG_HEX(dev, SLSI_TX, skb->data, skb->len < 128 ? skb->len : 128, "\n"); - - cb = slsi_skb_cb_init(skb); - cb->sig_length = fapi_sig_size(ma_unitdata_req); - cb->data_length = skb->len; - /* colour is defined as: */ - /* u16 register bits: - * 0 - do not use - * [2:1] - vif - * [7:3] - peer_index - * [10:8] - ac queue - */ - cb->colour = (slsi_frame_priority_to_ac_queue(skb->priority) << 8) | - (fapi_get_u16(skb, u.ma_unitdata_req.peer_index) << 3) | ndev_vif->ifnum << 1; - -#ifdef CONFIG_SCSC_WIFILOGGER - /* Log only the linear skb chunk ... unidata anywya will be truncated to 100.*/ - SCSC_WLOG_PKTFATE_LOG_TX_DATA_FRAME(fapi_get_u16(skb, u.ma_unitdata_req.host_tag), - skb->data, skb_headlen(skb)); -#endif - - /* ACCESS POINT MODE */ - if (ndev_vif->vif_type == FAPI_VIFTYPE_AP) { - struct ethhdr *ehdr = eth_hdr(skb); - - if (is_multicast_ether_addr(ehdr->h_dest)) { - ret = scsc_wifi_fcq_transmit_data(dev, - &ndev_vif->ap.group_data_qs, - slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3); - if (ret < 0) { - SLSI_NET_WARN(dev, "no fcq for groupcast, drop Tx frame\n"); - /* Free the local copy here ..if any */ - if (original_skb) - slsi_kfree_skb(skb); - return ret; - } - ret = scsc_wifi_transmit_frame(&sdev->hip4_inst, false, skb); - if (ret == NETDEV_TX_OK) { - /** - * Frees the original since the copy has already - * been freed downstream - */ - if (original_skb) - slsi_kfree_skb(original_skb); - return ret; - } else if (ret < 0) { - /* scsc_wifi_transmit_frame failed, decrement BoT counters */ - scsc_wifi_fcq_receive_data(dev, - &ndev_vif->ap.group_data_qs, - slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3); - if (original_skb) - slsi_kfree_skb(skb); - return ret; - } - if (original_skb) - slsi_kfree_skb(skb); - return -EIO; - } - } - slsi_spinlock_lock(&ndev_vif->peer_lock); - - peer = slsi_get_peer_from_mac(sdev, dev, eth_hdr(skb)->h_dest); - if (!peer) { - slsi_spinlock_unlock(&ndev_vif->peer_lock); - SLSI_NET_WARN(dev, "no peer record for %pM, drop Tx frame\n", eth_hdr(skb)->h_dest); - if (original_skb) - slsi_kfree_skb(skb); - return -EINVAL; - } - /** - * skb->priority will contain the priority obtained from the IP Diff/Serv field. - * The skb->priority field is defined in terms of the FAPI_PRIORITY_* definitions. - * For QoS enabled associations, this is the tid and is the value required in - * the ma_unitdata_req.priority field. For non-QoS assocations, the ma_unitdata_req. - * priority field requires FAPI_PRIORITY_CONTENTION. - */ - if (peer->qos_enabled) - fapi_set_u16(skb, u.ma_unitdata_req.priority, skb->priority); - - slsi_debug_frame(sdev, dev, skb, "TX"); - - ret = scsc_wifi_fcq_transmit_data(dev, &peer->data_qs, - slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3); - if (ret < 0) { - SLSI_NET_WARN(dev, "no fcq for %pM, drop Tx frame\n", eth_hdr(skb)->h_dest); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - if (original_skb) - slsi_kfree_skb(skb); - return ret; - } - - /* SKB is owned by scsc_wifi_transmit_frame() unless the transmission is - * unsuccesful. - */ - slsi_traffic_mon_event_tx(sdev, dev, skb); - ret = scsc_wifi_transmit_frame(&sdev->hip4_inst, false, skb); - if (ret != NETDEV_TX_OK) { - /* scsc_wifi_transmit_frame failed, decrement BoT counters */ - scsc_wifi_fcq_receive_data(dev, &peer->data_qs, slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3); - - if (ret == -ENOSPC) { - slsi_spinlock_unlock(&ndev_vif->peer_lock); - if (original_skb) - slsi_kfree_skb(skb); - return ret; - } - slsi_spinlock_unlock(&ndev_vif->peer_lock); - if (original_skb) - slsi_kfree_skb(skb); - return -EIO; - } - /* Frame has been successfully sent, and freed by lower layers */ - slsi_spinlock_unlock(&ndev_vif->peer_lock); - /* What about the original if we passed in a copy ? */ - if (original_skb) - slsi_kfree_skb(original_skb); - peer->sinfo.tx_bytes += len; - return ret; -} - -int slsi_tx_data_lower(struct slsi_dev *sdev, struct sk_buff *skb) -{ - struct net_device *dev; - struct netdev_vif *ndev_vif; - struct slsi_peer *peer; - u16 vif; - u8 *dest; - int ret; - struct slsi_skb_cb *cb = slsi_skb_cb_get(skb); - - vif = fapi_get_vif(skb); - - switch (fapi_get_u16(skb, u.ma_unitdata_req.data_unit_descriptor)) { - case FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME: - if (ntohs(eth_hdr(skb)->h_proto) == ETH_P_PAE || ntohs(eth_hdr(skb)->h_proto) == ETH_P_WAI) - return slsi_tx_control(sdev, NULL, skb); - dest = eth_hdr(skb)->h_dest; - break; - - case FAPI_DATAUNITDESCRIPTOR_AMSDU: - /* The AMSDU frame type is an AMSDU payload ready to be prepended by - * an 802.11 frame header by the firmware. The AMSDU subframe header - * is identical to an Ethernet header in terms of addressing, so it - * is safe to access the destination address through the ethernet - * structure. - */ - dest = eth_hdr(skb)->h_dest; - break; - case FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME: - dest = ieee80211_get_DA((struct ieee80211_hdr *)fapi_get_data(skb)); - break; - default: - SLSI_ERR(sdev, "data_unit_descriptor incorrectly set (0x%02x), dropping TX frame\n", - fapi_get_u16(skb, u.ma_unitdata_req.data_unit_descriptor)); - return -EINVAL; - } - - rcu_read_lock(); - dev = slsi_get_netdev_rcu(sdev, vif); - if (!dev) { - SLSI_ERR(sdev, "netdev(%d) No longer exists\n", vif); - rcu_read_unlock(); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - rcu_read_unlock(); - - if (is_multicast_ether_addr(dest) && ((ndev_vif->vif_type == FAPI_VIFTYPE_AP))) { - if (scsc_wifi_fcq_transmit_data(dev, &ndev_vif->ap.group_data_qs, - slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3) < 0) { - SLSI_NET_DBG3(dev, SLSI_TX, "no fcq for groupcast, dropping TX frame\n"); - return -EINVAL; - } - ret = scsc_wifi_transmit_frame(&sdev->hip4_inst, false, skb); - if (ret == NETDEV_TX_OK) - return ret; - /** - * This should be NEVER RETRIED/REQUEUED and its' handled - * by the caller in UDI cdev_write - */ - if (ret == -ENOSPC) - SLSI_NET_DBG1(dev, SLSI_TX, "TX_LOWER...Queue Full... BUT Dropping packet\n"); - else - SLSI_NET_DBG1(dev, SLSI_TX, "TX_LOWER...Generic Error...Dropping packet\n"); - /* scsc_wifi_transmit_frame failed, decrement BoT counters */ - scsc_wifi_fcq_receive_data(dev, &ndev_vif->ap.group_data_qs, - slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3); - return ret; - } - - slsi_spinlock_lock(&ndev_vif->peer_lock); - peer = slsi_get_peer_from_mac(sdev, dev, dest); - if (!peer) { - SLSI_ERR(sdev, "no peer record for %02x:%02x:%02x:%02x:%02x:%02x, dropping TX frame\n", - dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return -EINVAL; - } - slsi_debug_frame(sdev, dev, skb, "TX"); - - if (fapi_get_u16(skb, u.ma_unitdata_req.priority) == FAPI_PRIORITY_CONTENTION) - skb->priority = FAPI_PRIORITY_QOS_UP0; - else - skb->priority = fapi_get_u16(skb, u.ma_unitdata_req.priority); - - if (scsc_wifi_fcq_transmit_data(dev, &peer->data_qs, - slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3) < 0) { - SLSI_NET_DBG3(dev, SLSI_TX, "no fcq for %02x:%02x:%02x:%02x:%02x:%02x, dropping TX frame\n", - eth_hdr(skb)->h_dest[0], eth_hdr(skb)->h_dest[1], eth_hdr(skb)->h_dest[2], eth_hdr(skb)->h_dest[3], eth_hdr(skb)->h_dest[4], eth_hdr(skb)->h_dest[5]); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return -EINVAL; - } - /* SKB is owned by scsc_wifi_transmit_frame() unless the transmission is - * unsuccesful. - */ - ret = scsc_wifi_transmit_frame(&sdev->hip4_inst, false, skb); - if (ret < 0) { - SLSI_NET_DBG1(dev, SLSI_TX, "%s (signal: %d)\n", ret == -ENOSPC ? "Queue is full. Flow control" : "Failed to transmit", fapi_get_sigid(skb)); - /* scsc_wifi_transmit_frame failed, decrement BoT counters */ - scsc_wifi_fcq_receive_data(dev, &ndev_vif->ap.group_data_qs, - slsi_frame_priority_to_ac_queue(skb->priority), - sdev, - (cb->colour & 0x6) >> 1, - (cb->colour & 0xf8) >> 3); - if (ret == -ENOSPC) - SLSI_NET_DBG1(dev, SLSI_TX, - "TX_LOWER...Queue Full...BUT Dropping packet\n"); - else - SLSI_NET_DBG1(dev, SLSI_TX, - "TX_LOWER...Generic Error...Dropping packet\n"); - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return ret; - } - - slsi_spinlock_unlock(&ndev_vif->peer_lock); - return 0; -} - -/** - * NOTE: - * 1. dev can be NULL - * 2. On error the SKB is NOT freed, NOR retried (ENOSPC dropped). - * Callers should take care to free the SKB eventually. - */ -int slsi_tx_control(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - struct slsi_skb_cb *cb; - int res = 0; - struct fapi_signal_header *hdr; - - if (WARN_ON(!skb)) { - res = -EINVAL; - goto exit; - } - - /** - * Sanity check of the skb - if it's not an MLME, MA, debug or test - * signal it will be discarded. - * Skip if test mode (wlanlite) is enabled. - */ - if (!slsi_is_test_mode_enabled()) - if (!fapi_is_mlme(skb) && !fapi_is_ma(skb) && !fapi_is_debug(skb) && !fapi_is_test(skb)) { - SLSI_NET_WARN(dev, "Discarding skb because it has type: 0x%04X\n", fapi_get_sigid(skb)); - return -EINVAL; - } - - cb = slsi_skb_cb_init(skb); - cb->sig_length = fapi_get_expected_size(skb); - cb->data_length = skb->len; - /* F/w will panic if fw_reference is not zero. */ - hdr = (struct fapi_signal_header *)skb->data; - hdr->fw_reference = 0; - -#ifdef CONFIG_SCSC_WIFILOGGER - /* Log only the linear skb chunk */ - SCSC_WLOG_PKTFATE_LOG_TX_CTRL_FRAME(fapi_get_u16(skb, u.mlme_frame_transmission_ind.host_tag), - skb->data, skb_headlen(skb)); -#endif - - slsi_debug_frame(sdev, dev, skb, "TX"); - res = scsc_wifi_transmit_frame(&sdev->hip4_inst, true, skb); - if (res != NETDEV_TX_OK) { - char reason[80]; - - SLSI_NET_ERR(dev, "%s (signal %d)\n", res == -ENOSPC ? "Queue is full. Flow control" : "Failed to transmit", fapi_get_sigid(skb)); - - if (!in_interrupt()) { - snprintf(reason, sizeof(reason), "Failed to transmit signal 0x%04X (err:%d)", fapi_get_sigid(skb), res); - slsi_sm_service_failed(sdev, reason); - - res = -EIO; - } - } -exit: - return res; -} - -void slsi_tx_pause_queues(struct slsi_dev *sdev) -{ - if (!sdev) - return; - - scsc_wifi_fcq_pause_queues(sdev); -} - -void slsi_tx_unpause_queues(struct slsi_dev *sdev) -{ - if (!sdev) - return; - - scsc_wifi_fcq_unpause_queues(sdev); -} diff --git a/drivers/net/wireless/scsc/udi.c b/drivers/net/wireless/scsc/udi.c deleted file mode 100755 index 8fb287cfc075..000000000000 --- a/drivers/net/wireless/scsc/udi.c +++ /dev/null @@ -1,1175 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#include -#include -#include - -#include "dev.h" - -#include "hip.h" -#include "log_clients.h" -#include "mlme.h" -#include "fw_test.h" -#include "debug.h" -#include "udi.h" -#include "src_sink.h" -#include "unifiio.h" -#include "procfs.h" - -#ifdef SLSI_TEST_DEV -#include "unittest.h" -#define UDI_CHAR_DEVICE_NAME "s5n2560unittest" -#define UDI_CLASS_NAME "s5n2560test" -#else -#define UDI_CHAR_DEVICE_NAME "s5n2560udi" -#define UDI_CLASS_NAME "s5n2560" -#endif - -#define UDI_LOG_MASK_FILTER_NUM_MAX 5 - -#define UDI_MIB_SET_LEN_MAX 65535 -#define UDI_MIB_GET_LEN_MAX 2048 - -#ifndef ETH_P_WAPI -#define ETH_P_WAPI 0x88b4 -#endif - -#define SLSI_IP_TYPE_UDP 0x11 -#define SLSI_DHCP_SERVER_PORT 67 -#define SLSI_DHCP_CLIENT_PORT 68 -#define SLSI_DHCP_MAGIC_OFFSET 272 -#define SLSI_DHCP_MESSAGE_TYPE_ACK 0x05 - -/** - * Control character device for debug - * ================================== - */ -#define NUM_CHAR_CLIENTS 12 /* Number of client programmes on one node. */ - -#define MAX_MINOR (SLSI_UDI_MINOR_NODES - 1) /* Maximum node number. */ -static dev_t major_number; /* Major number of device created by system. */ -static struct class *class; /* Device class. */ - -struct slsi_cdev_client; - -struct slsi_cdev { - int minor; - struct cdev cdev; - struct slsi_cdev_client *client[NUM_CHAR_CLIENTS]; - - struct slsi_dev *sdev; - struct device *parent; -}; - -struct slsi_cdev_client { - struct slsi_cdev *ufcdev; - int log_enabled; - int log_allow_driver_signals; - - u16 tx_sender_id; - struct slsi_fw_test fw_test; - - /* Flags set for special filtering of ma_packet data */ - u16 ma_unitdata_filter_config; - - u16 ma_unitdata_size_limit; - - struct sk_buff_head log_list; - struct semaphore log_mutex; - wait_queue_head_t log_wq; - - /* Drop Frames and report the number dropped */ -#define UDI_MAX_QUEUED_FRAMES 10000 -#define UDI_RESTART_QUEUED_FRAMES 9000 - -#define UDI_MAX_QUEUED_DATA_FRAMES 9000 -#define UDI_RESTART_QUEUED_DATA_FRAMES 8000 - - /* Start dropping ALL frames at queue_len == UDI_MAX_QUEUED_FRAMES - * Restart queueing ALL frames at queue_len == UDI_RESTART_QUEUED_FRAMES - * Enable MA_PACKET filters at queue_len == UDI_MAX_QUEUED_DATA_FRAMES - * Disable MA_PACKET filters at queue_len == UDI_RESTART_QUEUED_DATA_FRAMES - */ - u32 log_dropped; - u32 log_dropped_data; - bool log_drop_data_packets; -}; - -static inline bool slsi_cdev_unitdata_filter_allow(struct slsi_cdev_client *client, u16 filter) -{ - return (client->ma_unitdata_filter_config & filter) == filter; -} - -/* One minor node per phy. In normal driver mode, this may be one. - * In unit test mode, this may be several. - */ -static struct slsi_cdev *uf_cdevs[SLSI_UDI_MINOR_NODES]; - -static int udi_log_event(struct slsi_log_client *log_client, struct sk_buff *skb, int dir); -static int send_signal_to_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir); -static int send_signal_to_inverse_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir); - -int slsi_check_cdev_refs(void) -{ - int client_num; - int cdev_num; - struct slsi_cdev *cdev = NULL; - - for (cdev_num = 0; cdev_num < SLSI_UDI_MINOR_NODES; cdev_num++) { - cdev = uf_cdevs[cdev_num]; - - if (!cdev) - continue; - - for (client_num = 0; client_num < NUM_CHAR_CLIENTS; client_num++) - if (cdev->client[client_num]) - return 1; - } - - return 0; -} - -int slsi_kernel_to_user_space_event(struct slsi_log_client *log_client, u16 event, u32 data_length, const u8 *data) -{ - struct slsi_cdev_client *client = log_client->log_client_ctx; - struct sk_buff *skb; - int ret; - - if (WARN_ON(!client)) - return -EINVAL; - - if (!client->log_allow_driver_signals) - return 0; - - skb = fapi_alloc_f(sizeof(struct fapi_signal_header), data_length, event, 0, __FILE__, __LINE__); - if (WARN_ON(!skb)) - return -ENOMEM; - - if (data_length) - fapi_append_data(skb, data, data_length); - - ret = udi_log_event(log_client, skb, UDI_CONFIG_IND); - if (ret) - SLSI_WARN_NODEV("Udi log event not registered\n"); - - /* udi_log_event takes a copy, so ensure that the skb allocated in this - * function is freed again. - */ - slsi_kfree_skb(skb); - return ret; -} - -static int slsi_cdev_open(struct inode *inode, struct file *file) -{ - struct slsi_cdev *uf_cdev; - struct slsi_cdev_client *client; - int indx; - int minor; - - minor = iminor(inode); - if (minor > MAX_MINOR) { - SLSI_ERR_NODEV("minor %d exceeds range\n", minor); - return -EINVAL; - } - - uf_cdev = uf_cdevs[minor]; - if (!uf_cdev) { - SLSI_ERR_NODEV("no cdev instance for minor %d\n", minor); - return -EINVAL; - } - - for (indx = 0; indx < NUM_CHAR_CLIENTS; indx++) - if (!uf_cdev->client[indx]) - break; - if (indx >= NUM_CHAR_CLIENTS) { - SLSI_ERR_NODEV("already opened\n"); - return -ENOTSUPP; - } - - client = kmalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return -ENOMEM; - memset(client, 0, sizeof(struct slsi_cdev_client)); - - /* init other resource */ - skb_queue_head_init(&client->log_list); - init_waitqueue_head(&client->log_wq); - sema_init(&client->log_mutex, 1); - client->tx_sender_id = SLSI_TX_PROCESS_ID_UDI_MIN; - slsi_fw_test_init(uf_cdev->sdev, &client->fw_test); - - client->ufcdev = uf_cdev; - uf_cdev->client[indx] = client; - file->private_data = client; - slsi_procfs_inc_node(); - -#ifdef CONFIG_SCSC_MXLOGGER - scsc_service_register_observer(NULL, "udi"); -#endif - - SLSI_DBG1_NODEV(SLSI_UDI, "Client:%d added\n", indx); - - return 0; -} - -static int slsi_cdev_release(struct inode *inode, struct file *filp) -{ - struct slsi_cdev_client *client = (void *)filp->private_data; - struct slsi_cdev *uf_cdev; - int indx; - int minor; - - minor = iminor(inode); - if (minor > MAX_MINOR) { - SLSI_ERR_NODEV("minor %d exceeds range\n", minor); - return -EINVAL; - } - - uf_cdev = uf_cdevs[minor]; - if (!uf_cdev) { - SLSI_ERR_NODEV("no cdev instance for minor %d\n", minor); - return -EINVAL; - } - - if (!client) - return -EINVAL; - - for (indx = 0; indx < NUM_CHAR_CLIENTS; indx++) - if (uf_cdev->client[indx] == client) - break; - if (indx >= NUM_CHAR_CLIENTS) { - SLSI_ERR_NODEV("client not found in list\n"); - return -EINVAL; - } - - if (waitqueue_active(&client->log_wq)) - wake_up_interruptible(&client->log_wq); - - if (client->log_enabled) - slsi_log_client_unregister(client->ufcdev->sdev, client); - - slsi_skb_queue_purge(&client->log_list); - - slsi_fw_test_deinit(uf_cdev->sdev, &client->fw_test); - uf_cdev->client[indx] = NULL; - - /* free other resource */ - kfree(client); - slsi_procfs_dec_node(); - -#ifdef CONFIG_SCSC_MXLOGGER - scsc_service_unregister_observer(NULL, "udi"); -#endif - - SLSI_DBG1_NODEV(SLSI_UDI, "Client:%d removed\n", indx); - - return 0; -} - -static ssize_t slsi_cdev_read(struct file *filp, char *p, size_t len, loff_t *poff) -{ - struct slsi_cdev_client *client = (void *)filp->private_data; - struct slsi_dev *sdev; - int msglen; - struct sk_buff *skb; - - SLSI_UNUSED_PARAMETER(poff); - - if (!client) - return -EINVAL; - - if (!skb_queue_len(&client->log_list)) { - if (filp->f_flags & O_NONBLOCK) - return 0; - - /* wait until getting a signal */ - if (wait_event_interruptible(client->log_wq, skb_queue_len(&client->log_list))) { - SLSI_ERR_NODEV("slsi_cdev_read: wait_event_interruptible failed.\n"); - return -ERESTARTSYS; - } - } - - sdev = client->ufcdev->sdev; - if (!sdev) { - SLSI_ERR_NODEV("sdev not set\n"); - return -EINVAL; - } - - skb = slsi_skb_dequeue(&client->log_list); - if (!skb) { - SLSI_ERR(sdev, "No Data\n"); - return -EINVAL; - } - - slsi_fw_test_signal_with_udi_header(sdev, &client->fw_test, skb); - - msglen = skb->len; - if (msglen > (s32)len) { - SLSI_WARN(sdev, "truncated read to %d actual msg len is %lu\n", msglen, (unsigned long int)len); - msglen = len; - } - - if (copy_to_user(p, skb->data, msglen)) { - SLSI_ERR(sdev, "Failed to copy UDI log to user\n"); - slsi_kfree_skb(skb); - return -EFAULT; - } - - slsi_kfree_skb(skb); - return msglen; -} - -static ssize_t slsi_cdev_write(struct file *filp, const char *p, size_t len, loff_t *poff) -{ - struct slsi_cdev_client *client; - struct slsi_dev *sdev; - struct sk_buff *skb; - u8 *data; - struct slsi_skb_cb *cb; - - SLSI_UNUSED_PARAMETER(poff); - - client = (void *)filp->private_data; - if (!client) { - SLSI_ERR_NODEV("filep private data not set\n"); - return -EINVAL; - } - - if (!client->ufcdev) { - SLSI_ERR_NODEV("ufcdev not set\n"); - return -EINVAL; - } - - sdev = client->ufcdev->sdev; - if (!sdev) { - SLSI_ERR_NODEV("sdev not set\n"); - return -EINVAL; - } - skb = slsi_alloc_skb_headroom(len, GFP_KERNEL); - data = skb_put(skb, len); - if (copy_from_user(data, p, len)) { - SLSI_ERR(sdev, "copy from user failed\n"); - slsi_kfree_skb(skb); - return -EFAULT; - } - - cb = slsi_skb_cb_init(skb); - cb->sig_length = fapi_get_expected_size(skb); - cb->data_length = skb->len; - /* colour is defined as: */ - /* u16 register bits: - * 0 - do not use - * [2:1] - vif - * [7:3] - peer_index - * [10:8] - ac queue - */ - if (fapi_is_ma(skb)) - cb->colour = (slsi_frame_priority_to_ac_queue(skb->priority) << 8) | - (fapi_get_u16(skb, u.ma_unitdata_req.peer_index) << 3) | (fapi_get_u16(skb, u.ma_unitdata_req.vif) << 1); - - /* F/w will panic if fw_reference is not zero. */ - fapi_set_u32(skb, fw_reference, 0); - /* set mac header uses values from above initialized cb */ - skb_set_mac_header(skb, fapi_get_data(skb) - skb->data); - - SLSI_DBG3_NODEV(SLSI_UDI, - "UDI Signal:%.4X SigLEN:%d DataLen:%d SKBHeadroom:%d bytes:%d\n", - fapi_get_sigid(skb), fapi_get_siglen(skb), - fapi_get_datalen(skb), skb_headroom(skb), (int)len); - - /* In WlanLite test mode req signals IDs are 0x1000, 0x1002, 0x1004 */ - if (slsi_is_test_mode_enabled() || fapi_is_req(skb) || fapi_is_res(skb)) { - /* Use the range of PIDs allocated to the udi clients */ - client->tx_sender_id++; - if (client->tx_sender_id > SLSI_TX_PROCESS_ID_UDI_MAX) - client->tx_sender_id = SLSI_TX_PROCESS_ID_UDI_MIN; - - fapi_set_u16(skb, sender_pid, client->tx_sender_id); - if (!slsi_is_test_mode_enabled()) - slsi_fw_test_signal(sdev, &client->fw_test, skb); - if (fapi_is_ma(skb)) { - if (slsi_tx_data_lower(sdev, skb)) { - slsi_kfree_skb(skb); - return -EINVAL; - } - } else if (slsi_tx_control(sdev, NULL, skb)) { - slsi_kfree_skb(skb); - return -EINVAL; - } - } else if (slsi_hip_rx(sdev, skb)) { - slsi_kfree_skb(skb); - return -EINVAL; - } - - return len; -} - -static long slsi_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct slsi_cdev_client *client = (void *)filp->private_data; - struct slsi_dev *sdev; - long r = 0; - int int_param; - u32 mib_data_length; /* Length of valid Mib data in the buffer */ - u32 mib_data_size; /* Size of the mib buffer */ - unsigned char *mib_data; /* Mib Input/Output Buffer */ - u16 mib_vif; - - if (!client || !client->ufcdev) - return -EINVAL; - sdev = client->ufcdev->sdev; - - slsi_wakelock(&sdev->wlan_wl); - - switch (cmd) { - case UNIFI_GET_UDI_ENABLE: - int_param = client->log_enabled; - put_user(int_param, (int *)arg); - break; - - case UNIFI_SET_UDI_ENABLE: - if (get_user(int_param, (int *)arg)) { - r = -EFAULT; - break; - } - - if (int_param) { - slsi_log_client_register(sdev, client, udi_log_event, NULL, 0, 0); - client->log_enabled = 1; - if (int_param > 1) - client->log_allow_driver_signals = 1; - } else { - slsi_log_client_unregister(sdev, client); - client->log_enabled = 0; - } - - break; - - case UNIFI_SET_UDI_LOG_CONFIG: - { - struct unifiio_udi_config_t config; - - if (copy_from_user(&config, (void *)arg, sizeof(config))) { - SLSI_ERR(sdev, "UNIFI_SET_UDI_LOG_CONFIG: Failed to copy from userspace\n"); - r = -EFAULT; - break; - } - - client->ma_unitdata_size_limit = config.ma_unitdata_size_limit; - break; - } - case UNIFI_SET_UDI_LOG_MASK: - { - struct unifiio_filter_t filter; - int i; - - /* to minimise load on data path, list is converted here to array indexed by signal number */ - if (copy_from_user(&filter, (void *)arg, sizeof(filter))) { - SLSI_ERR(sdev, "UNIFI_SET_UDI_LOG_MASK: Failed to copy from userspace\n"); - r = -EFAULT; - break; - } - - if (unlikely(filter.signal_ids_n > UDI_LOG_MASK_FILTER_NUM_MAX)) { - SLSI_ERR(sdev, "UNIFI_SET_UDI_LOG_MASK: number of filters too long\n"); - r = -EFAULT; - break; - } - - if (filter.signal_ids_n) { - char *signal_filter_index; - int max; - int min; - - max = filter.signal_ids[0]; - min = filter.signal_ids[0]; - - /* find maximum and minimum signal id in filter */ - for (i = 0; i < filter.signal_ids_n; i++) { - if (filter.signal_ids[i] & UDI_MA_UNITDATA_FILTER_ALLOW_MASK) { - client->ma_unitdata_filter_config |= filter.signal_ids[i]; - continue; - } - if (filter.signal_ids[i] > max) - max = filter.signal_ids[i]; - else if (filter.signal_ids[i] < min) - min = filter.signal_ids[i]; - } - /* and create array only big enough to index the range of signal id specified */ - signal_filter_index = kmalloc(max - min + 1, GFP_KERNEL); - if (signal_filter_index) { - memset(signal_filter_index, 0, max - min + 1); - for (i = 0; i < filter.signal_ids_n; i++) { - if (filter.signal_ids[i] & UDI_MA_UNITDATA_FILTER_ALLOW_MASK) - continue; - signal_filter_index[filter.signal_ids[i] - min] = 1; - } - slsi_log_client_unregister(sdev, client); - slsi_log_client_register(sdev, client, - filter.log_listed_flag ? send_signal_to_inverse_log_filter : - send_signal_to_log_filter, signal_filter_index, min, max); - } else { - r = -ENOMEM; - } - } - break; - } - case UNIFI_SET_MIB: - { - struct net_device *dev = NULL; - - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Device not yet available\n"); - r = -EFAULT; - break; - } - - /* First 2 Bytes are the VIF */ - if (copy_from_user((void *)&mib_vif, (void *)arg, 2)) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Failed to copy in vif\n"); - r = -EFAULT; - break; - } - - /* First 4 Bytes are the Number of Bytes of input Data */ - if (copy_from_user((void *)&mib_data_length, (void *)(arg + 2), 4)) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Failed to copy in mib_data_length\n"); - r = -EFAULT; - break; - } - - /* Second 4 Bytes are the size of the Buffer */ - if (copy_from_user((void *)&mib_data_size, (void *)(arg + 6), 4)) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Failed to copy in mib_data_size\n"); - r = -EFAULT; - break; - } - - /* check if length is valid */ - if (unlikely(mib_data_length > UDI_MIB_SET_LEN_MAX || mib_data_size > UDI_MIB_SET_LEN_MAX)) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: size too long (mib_data_length:%u mib_data_size:%u)\n", mib_data_length, mib_data_size); - r = -EFAULT; - break; - } - - mib_data = kmalloc(mib_data_size, GFP_KERNEL); - - /* Read the rest of the Mib Data */ - if (copy_from_user((void *)mib_data, (void *)(arg + 10), mib_data_length)) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Failed to copy in mib_data\n"); - kfree(mib_data); - r = -EFAULT; - break; - } - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - dev = slsi_get_netdev_locked(sdev, mib_vif); - if (mib_vif != 0 && !dev) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Failed - net_device is NULL for interface = %d\n", mib_vif); - kfree(mib_data); - r = -EFAULT; - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - break; - } - - r = slsi_mlme_set(sdev, dev, mib_data, mib_data_length); - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - kfree(mib_data); - break; - } - case UNIFI_GET_MIB: - { - struct net_device *dev = NULL; - - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: Device not yet available\n"); - r = -EFAULT; - break; - } - - /* First 2 Bytes are the VIF */ - if (copy_from_user((void *)&mib_vif, (void *)arg, 2)) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Failed to copy in vif\n"); - r = -EFAULT; - break; - } - - /* First 4 Bytes are the Number of Bytes of input Data */ - if (copy_from_user((void *)&mib_data_length, (void *)(arg + 2), 4)) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: Failed to copy in mib_data_length\n"); - r = -EFAULT; - break; - } - - /* Second 4 Bytes are the size of the Buffer */ - if (copy_from_user((void *)&mib_data_size, (void *)(arg + 6), 4)) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: Failed to copy in mib_data_size\n"); - r = -EFAULT; - break; - } - - /* check if length is valid */ - if (unlikely(mib_data_length > UDI_MIB_GET_LEN_MAX || mib_data_size > UDI_MIB_GET_LEN_MAX)) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: size too long (mib_data_length:%u mib_data_size:%u)\n", mib_data_length, mib_data_size); - r = -EFAULT; - break; - } - - mib_data = kmalloc(mib_data_size, GFP_KERNEL); - - /* Read the rest of the Mib Data */ - if (copy_from_user((void *)mib_data, (void *)(arg + 10), mib_data_length)) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: Failed to copy in mib_data\n"); - kfree(mib_data); - r = -EFAULT; - break; - } - - SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex); - dev = slsi_get_netdev_locked(sdev, mib_vif); - if (mib_vif != 0 && !dev) { - SLSI_ERR(sdev, "UNIFI_SET_MIB: Failed - net_device is NULL for interface = %d\n", mib_vif); - kfree(mib_data); - r = -EFAULT; - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - break; - } - if (slsi_mlme_get(sdev, dev, mib_data, mib_data_length, mib_data, mib_data_size, &mib_data_length)) { - kfree(mib_data); - r = -EINVAL; - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - break; - } - - SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex); - - /* Check the buffer is big enough */ - if (mib_data_length > mib_data_size) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: Mib result data is to long. (%d bytes when the max is %d bytes)\n", mib_data_length, mib_data_size); - kfree(mib_data); - r = -EINVAL; - break; - } - - /* Copy back the number of Bytes in the Mib result */ - if (copy_to_user((void *)arg, (void *)&mib_data_length, 4)) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: Failed to copy in mib_data_length back to user\n"); - kfree(mib_data); - r = -EINVAL; - break; - } - - /* Copy back the Mib data */ - if (copy_to_user((void *)(arg + 4), mib_data, mib_data_length)) { - SLSI_ERR(sdev, "UNIFI_GET_MIB: Failed to copy in mib_data back to user\n"); - kfree(mib_data); - r = -EINVAL; - break; - } - kfree(mib_data); - break; - } - case UNIFI_SRC_SINK_IOCTL: - if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { - SLSI_ERR(sdev, "UNIFI_SRC_SINK_IOCTL: Device not yet available\n"); - r = -EFAULT; - break; - } - r = slsi_src_sink_cdev_ioctl_cfg(sdev, arg); - break; - - case UNIFI_SOFTMAC_CFG: - { - u32 softmac_cmd; - u8 cmd_param_size; - - SLSI_ERR(sdev, "UNIFI_SOFTMAC_CFG\n"); - - if (copy_from_user((void *)&softmac_cmd, (void *)arg, 4)) { - SLSI_ERR(sdev, "Failed to get the command\n"); - r = -EFAULT; - break; - } - SLSI_DBG3_NODEV(SLSI_UDI, "softmac_cmd -> %u\n", softmac_cmd); - - arg += sizeof(softmac_cmd); /* Advance past the command bit */ - if (copy_from_user((void *)&cmd_param_size, (void *)(arg + 4), 1)) { - SLSI_ERR(sdev, "Failed to get the command size\n"); - r = -EFAULT; - break; - } - SLSI_DBG3_NODEV(SLSI_UDI, "cmd_param_size -> %u\n", cmd_param_size); - - if (cmd_param_size) - client->ma_unitdata_filter_config = UDI_MA_UNITDATA_FILTER_ALLOW_EAPOL_ID; - else - client->ma_unitdata_filter_config = 0; - break; - } - default: - SLSI_WARN(sdev, "Operation (%d) not supported\n", cmd); - r = -EINVAL; - } - - slsi_wakeunlock(&sdev->wlan_wl); - return r; -} - -static unsigned int slsi_cdev_poll(struct file *filp, poll_table *wait) -{ - struct slsi_cdev_client *client = (void *)filp->private_data; - - SLSI_DBG4_NODEV(SLSI_UDI, "Poll(%d)\n", skb_queue_len(&client->log_list)); - - if (skb_queue_len(&client->log_list)) - return POLLIN | POLLRDNORM; /* readable */ - - poll_wait(filp, &client->log_wq, wait); - - if (skb_queue_len(&client->log_list)) - return POLLIN | POLLRDNORM; /* readable */ - - return 0; -} - -/* we know for sure that there is a filter present in log_client->signal_filter if this function is called. - * we know this because it is called only through a function pointer that is assigned - * only when a filter is also set up in the log_client - */ -static int send_signal_to_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir) -{ - int ret = 0; - u16 signal_id = fapi_get_sigid(skb); - - if (signal_id > log_client->max_signal_id || signal_id < log_client->min_signal_id || !log_client->signal_filter[signal_id - log_client->min_signal_id]) - ret = udi_log_event(log_client, skb, dir); - - return ret; -} - -static int send_signal_to_inverse_log_filter(struct slsi_log_client *log_client, struct sk_buff *skb, int dir) -{ - int ret = 0; - u16 signal_id = fapi_get_sigid(skb); - - if (signal_id <= log_client->max_signal_id && signal_id >= log_client->min_signal_id && log_client->signal_filter[signal_id - log_client->min_signal_id]) - ret = udi_log_event(log_client, skb, dir); - - return ret; -} - -static bool is_allowed_ip_frame(struct ethhdr *ehdr, u16 signal_id) -{ - u8 *ip_frame = ((u8 *)ehdr) + sizeof(struct ethhdr); - u8 *ip_data; - u16 ip_data_offset = 20; - /*u8 version = ip_frame[0] >> 4; */ - u8 hlen = ip_frame[0] & 0x0F; - /*u8 tos = ip_frame[1]; */ - /*u16 len = ip_frame[2] << 8 | frame[3]; */ - /*u16 id = ip_frame[4] << 8 | frame[5]; */ - /*u16 flags_foff = ip_frame[6] << 8 | frame[7]; */ - /*u8 ttl = ip_frame[8]; */ - u8 ip_proto = ip_frame[9]; - - /*u16 cksum = ip_frame[10] << 8 | frame[11]; */ - /*u8 *src_ip = &ip_frame[12];*/ - /*u8 *dest_ip = &ip_frame[16];*/ - - SLSI_UNUSED_PARAMETER(signal_id); - - if (hlen > 5) - ip_data_offset += (hlen - 5) * 4; - - ip_data = ip_frame + ip_data_offset; - - switch (ip_proto) { - case SLSI_IP_TYPE_UDP: - { - u16 srcport = ip_data[0] << 8 | ip_data[1]; - u16 dstport = ip_data[2] << 8 | ip_data[3]; - - SLSI_DBG3_NODEV(SLSI_UDI, "FILTER(0x%.4X) Key -> Proto(0x%.4X) -> IpProto(%d) ->UDP(s:%d, d:%d)\n", signal_id, ntohs(ehdr->h_proto), ip_proto, srcport, dstport); - if (srcport == SLSI_DHCP_CLIENT_PORT || srcport == SLSI_DHCP_SERVER_PORT || - dstport == SLSI_DHCP_CLIENT_PORT || dstport == SLSI_DHCP_SERVER_PORT) { - SLSI_DBG3_NODEV(SLSI_UDI, "FILTER(0x%.4X) Key -> Proto(0x%.4X) -> IpProto(%d) ->UDP(s:%d, d:%d) ALLOW\n", signal_id, ntohs(ehdr->h_proto), ip_proto, srcport, dstport); - return true; - } - } - default: - break; - } - - return false; -} - -static int udi_log_event(struct slsi_log_client *log_client, struct sk_buff *skb, int dir) -{ - struct slsi_cdev_client *client = log_client->log_client_ctx; - struct udi_msg_t msg; - struct udi_msg_t *msg_skb; - u16 signal_id = fapi_get_sigid(skb); - - if (WARN_ON(!client)) - return -EINVAL; - if (WARN_ON(!skb)) - return -EINVAL; - if (WARN_ON(skb->len == 0)) - return -EINVAL; - - /* Special Filtering of MaPacket frames */ - if (slsi_cdev_unitdata_filter_allow(client, UDI_MA_UNITDATA_FILTER_ALLOW_MASK) && - (signal_id == MA_UNITDATA_REQ || signal_id == MA_UNITDATA_IND)) { - u16 frametype; - - SLSI_DBG4_NODEV(SLSI_UDI, "FILTER(0x%.4X)\n", signal_id); - if (signal_id == MA_UNITDATA_REQ) - frametype = fapi_get_u16(skb, u.ma_unitdata_req.data_unit_descriptor); - else - frametype = fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor); - SLSI_DBG4_NODEV(SLSI_UDI, "FILTER(0x%.4X) frametype:%d\n", signal_id, frametype); - - if (frametype == FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME) { - struct ethhdr *ehdr = (struct ethhdr *)fapi_get_data(skb); - - if (signal_id == MA_UNITDATA_REQ) - ehdr = (struct ethhdr *)fapi_get_data(skb); - - if (slsi_cdev_unitdata_filter_allow(client, UDI_MA_UNITDATA_FILTER_ALLOW_EAPOL_ID) || - slsi_cdev_unitdata_filter_allow(client, UDI_MA_UNITDATA_FILTER_ALLOW_KEY_ID)) { - SLSI_DBG4_NODEV(SLSI_UDI, "FILTER(0x%.4X) Eap -> Proto(0x%.4X)\n", signal_id, ntohs(ehdr->h_proto)); - switch (ntohs(ehdr->h_proto)) { - case ETH_P_PAE: - case ETH_P_WAI: - SLSI_DBG4_NODEV(SLSI_UDI, "FILTER(0x%.4X) Eap -> Proto(0x%.4X) ALLOW\n", signal_id, ntohs(ehdr->h_proto)); - goto allow_frame; - default: - break; - } - } - - if (slsi_cdev_unitdata_filter_allow(client, UDI_MA_UNITDATA_FILTER_ALLOW_KEY_ID)) { - SLSI_DBG4_NODEV(SLSI_UDI, "FILTER(0x%.4X) Key -> Proto(0x%.4X)\n", signal_id, ntohs(ehdr->h_proto)); - switch (ntohs(ehdr->h_proto)) { - case ETH_P_ARP: - SLSI_DBG4_NODEV(SLSI_UDI, "FILTER(0x%.4X) Key -> Proto(0x%.4X) -> Arp ALLOW\n", signal_id, ntohs(ehdr->h_proto)); - goto allow_frame; - case ETH_P_IP: - if (is_allowed_ip_frame(ehdr, signal_id)) - goto allow_frame; - default: - break; - } - } - } - if (frametype == FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME) - if (slsi_cdev_unitdata_filter_allow(client, UDI_MA_UNITDATA_FILTER_ALLOW_MGT_ID)) - if (ieee80211_is_mgmt(fapi_get_mgmt(skb)->frame_control)) - goto allow_frame; - - SLSI_DBG4_NODEV(SLSI_UDI, "FILTER(0x%.4X) DROP\n", signal_id); - - if (down_interruptible(&client->log_mutex)) { - SLSI_WARN_NODEV("Failed to get udi sem\n"); - return -ERESTARTSYS; - } - if (client->log_drop_data_packets) - client->log_dropped_data++; - up(&client->log_mutex); - return -ECANCELED; - } - - /* Special Filtering of MaPacketCfm. - * Only log ma_packet_cfm if the tx status != Success - */ - if (signal_id == MA_UNITDATA_CFM && slsi_cdev_unitdata_filter_allow(client, UDI_MA_UNITDATA_FILTER_ALLOW_CFM_ERROR_ID)) - if (fapi_get_u16(skb, u.ma_unitdata_cfm.transmission_status) == FAPI_TRANSMISSIONSTATUS_SUCCESSFUL) - return -ECANCELED; - - /* Exception for driver configuration frames. - * these frames must be sent irrespective of number of frames - * in queue. - */ - if (dir == UDI_CONFIG_IND) - goto allow_config_frame; - -allow_frame: - if (down_interruptible(&client->log_mutex)) { - SLSI_WARN_NODEV("Failed to get udi sem\n"); - return -ERESTARTSYS; - } - - /* Handle hitting the UDI_MAX_QUEUED_FRAMES Limit */ - if (client->log_dropped) { - if (skb_queue_len(&client->log_list) <= UDI_RESTART_QUEUED_FRAMES) { - u32 dropped = client->log_dropped; - - SLSI_WARN_NODEV("Stop Dropping UDI Frames : %d frames Dropped\n", dropped); - client->log_dropped = 0; - up(&client->log_mutex); - slsi_kernel_to_user_space_event(log_client, UDI_DRV_DROPPED_FRAMES, sizeof(u32), (u8 *)&dropped); - return -ECANCELED; - } - client->log_dropped++; - up(&client->log_mutex); - return -ECANCELED; - } else if (!client->log_dropped && skb_queue_len(&client->log_list) >= UDI_MAX_QUEUED_FRAMES) { - SLSI_WARN_NODEV("Start Dropping UDI Frames\n"); - client->log_dropped++; - up(&client->log_mutex); - return -ECANCELED; - } - - /* Handle hitting the UDI_MAX_QUEUED_DATA_FRAMES Limit - * Turn ON the MA_PACKET Filters before we get near the absolute limit of UDI_MAX_QUEUED_FRAMES - * This should allow key frames (mgt, dhcp and eapol etc) to still be in the logs but stop the logging general data frames. - * This occurs when the Transfer rate is higher than we can take the frames out of the UDI list. - */ - if (client->log_drop_data_packets && skb_queue_len(&client->log_list) < UDI_RESTART_QUEUED_DATA_FRAMES) { - u32 dropped = client->log_dropped_data; - - SLSI_WARN_NODEV("Stop Dropping UDI Frames : %d Basic Data frames Dropped\n", client->log_dropped_data); - client->log_drop_data_packets = false; - client->ma_unitdata_filter_config = 0; - client->log_dropped_data = 0; - up(&client->log_mutex); - slsi_kernel_to_user_space_event(log_client, UDI_DRV_DROPPED_DATA_FRAMES, sizeof(u32), (u8 *)&dropped); - return -ECANCELED; - } else if (!client->log_drop_data_packets && skb_queue_len(&client->log_list) >= UDI_MAX_QUEUED_DATA_FRAMES && !slsi_cdev_unitdata_filter_allow(client, UDI_MA_UNITDATA_FILTER_ALLOW_MASK)) { - SLSI_WARN_NODEV("Start Dropping UDI Basic Data Frames\n"); - client->log_drop_data_packets = true; - client->ma_unitdata_filter_config = UDI_MA_UNITDATA_FILTER_ALLOW_MGT_ID | - UDI_MA_UNITDATA_FILTER_ALLOW_KEY_ID | - UDI_MA_UNITDATA_FILTER_ALLOW_CFM_ERROR_ID | - UDI_MA_UNITDATA_FILTER_ALLOW_EAPOL_ID; - } - up(&client->log_mutex); - -allow_config_frame: - if ((signal_id == MA_UNITDATA_REQ || signal_id == MA_UNITDATA_IND) && - (client->ma_unitdata_size_limit) && (skb->len > client->ma_unitdata_size_limit)) { - struct slsi_skb_cb *cb; - struct sk_buff *skb2 = alloc_skb(sizeof(msg) + client->ma_unitdata_size_limit, GFP_ATOMIC); - - if (WARN_ON(!skb2)) - return -ENOMEM; - - skb_reserve(skb2, sizeof(msg)); - cb = slsi_skb_cb_init(skb2); - cb->sig_length = fapi_get_siglen(skb); - cb->data_length = client->ma_unitdata_size_limit; - skb_copy_bits(skb, 0, skb_put(skb2, client->ma_unitdata_size_limit), client->ma_unitdata_size_limit); - skb = skb2; - } else { - skb = slsi_skb_copy_expand(skb, sizeof(msg), 0, GFP_ATOMIC); - if (WARN_ON(!skb)) - return -ENOMEM; - } - - msg.length = sizeof(msg) + skb->len; - msg.timestamp = ktime_to_ms(ktime_get()); - msg.direction = dir; - msg.signal_length = fapi_get_siglen(skb); - - msg_skb = (struct udi_msg_t *)skb_push(skb, sizeof(msg)); - *msg_skb = msg; - - slsi_skb_queue_tail(&client->log_list, skb); - - /* Wake any waiting user process */ - wake_up_interruptible(&client->log_wq); - - return 0; -} - -#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ - device_create(_class, _parent, _devno, _priv, _fmt, _args) - -static const struct file_operations slsi_cdev_fops = { - .owner = THIS_MODULE, - .open = slsi_cdev_open, - .release = slsi_cdev_release, - .read = slsi_cdev_read, - .write = slsi_cdev_write, - .unlocked_ioctl = slsi_cdev_ioctl, - .compat_ioctl = slsi_cdev_ioctl, - .poll = slsi_cdev_poll, -}; - -#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ - device_create(_class, _parent, _devno, _priv, _fmt, _args) - -#ifndef SLSI_TEST_DEV -static int slsi_get_minor(void) -{ - int minor; - - for (minor = 0; minor < SLSI_UDI_MINOR_NODES; minor++) - if (!uf_cdevs[minor]) - return minor; - return -1; -} -#endif - -static int slsi_cdev_create(struct slsi_dev *sdev, struct device *parent) -{ - dev_t devno; - int ret; - struct slsi_cdev *pdev; - int minor; - - SLSI_DBG3_NODEV(SLSI_UDI, "\n"); -#ifdef SLSI_TEST_DEV - { - /* Use the same minor as the unittesthip char device so the number match */ - struct slsi_test_dev *uftestdev = (struct slsi_test_dev *)sdev->maxwell_core; - - minor = uftestdev->device_minor_number; - if (uf_cdevs[minor]) - return -EINVAL; - } -#else - minor = slsi_get_minor(); -#endif - if (minor < 0) { - SLSI_ERR(sdev, "no minor numbers available\n"); - return -ENOMEM; - } - - pdev = kmalloc(sizeof(*pdev), GFP_KERNEL); - if (!pdev) - return -ENOMEM; - memset(pdev, 0, sizeof(*pdev)); - - cdev_init(&pdev->cdev, &slsi_cdev_fops); - pdev->cdev.owner = THIS_MODULE; - pdev->minor = minor; - devno = MKDEV(MAJOR(major_number), minor); - ret = cdev_add(&pdev->cdev, devno, 1); - if (ret) { - SLSI_ERR(sdev, "cdev_add failed with %d for minor %d\n", ret, minor); - kfree(pdev); - return ret; - } - - pdev->sdev = sdev; - pdev->parent = parent; - if (!UF_DEVICE_CREATE(class, pdev->parent, devno, pdev, UDI_CHAR_DEVICE_NAME "%d", minor)) { - cdev_del(&pdev->cdev); - kfree(pdev); - return -EINVAL; - } - sdev->uf_cdev = (void *)pdev; - sdev->procfs_instance = minor; - uf_cdevs[minor] = pdev; - - return 0; -} - -static void slsi_cdev_destroy(struct slsi_dev *sdev) -{ - struct slsi_cdev *pdev = (struct slsi_cdev *)sdev->uf_cdev; - struct kobject *kobj; - struct kref *kref; - - if (!pdev) - return; - - SLSI_DBG1(sdev, SLSI_UDI, "\n"); - while (slsi_check_cdev_refs()) { - SLSI_ERR(sdev, "UDI Client still attached. Please Terminate!\n"); - msleep(1000); - } - - /* There exist a possibility of race such that the - * - * - file operation release callback (slsi_cdev_release) is called - * - the cdev client structure is freed - * - the context is pre-empted and this context (slsi_cdev_destroy) is executed - * - slsi_cdev_destroy deletes cdev and hence the kobject embedded inside cdev - * and returns - * - the release context again executes and operates on a non-existent kobject - * leading to kernel Panic - * - * Ideally the kernel should protect against such race. But it is not! - * So we check here that the file operation release callback is complete by - * checking the refcount in the kobject embedded in cdev structure. - * The refcount is initialized to 1; so anything more than that means - * there exists attached clients. - */ - - kobj = &pdev->cdev.kobj; - kref = &kobj->kref; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) - while (refcount_read(&kref->refcount) > 1) { - SLSI_WARN(sdev, "UDI client File op release not completed yet! (count=%d)\n", refcount_read(&kref->refcount)); - msleep(50); - } -#else - while (atomic_read(&kref->refcount) > 1) { - SLSI_WARN(sdev, "UDI client File op release not completed yet! (count=%d)\n", atomic_read(&kref->refcount)); - msleep(50); - } -#endif - device_destroy(class, pdev->cdev.dev); - cdev_del(&pdev->cdev); - sdev->uf_cdev = NULL; - uf_cdevs[pdev->minor] = NULL; - kfree(pdev); -} - -static int udi_initialised; - -int slsi_udi_init(void) -{ - int ret; - - SLSI_DBG1_NODEV(SLSI_UDI, "\n"); - memset(uf_cdevs, 0, sizeof(uf_cdevs)); - - /* Allocate two device numbers for each device. */ - ret = alloc_chrdev_region(&major_number, 0, SLSI_UDI_MINOR_NODES, UDI_CLASS_NAME); - if (ret) { - SLSI_ERR_NODEV("Failed to add alloc dev numbers: %d\n", ret); - return ret; - } - - /* Create a driver class */ - class = class_create(THIS_MODULE, UDI_CLASS_NAME); - if (IS_ERR(class)) { - SLSI_ERR_NODEV("Failed to create driver udi class\n"); - unregister_chrdev_region(major_number, SLSI_UDI_MINOR_NODES); - major_number = 0; - return -EINVAL; - } - - udi_initialised = 1; - - return 0; -} - -int slsi_udi_deinit(void) -{ - if (!udi_initialised) - return -1; - SLSI_DBG1_NODEV(SLSI_UDI, "\n"); - class_destroy(class); - unregister_chrdev_region(major_number, SLSI_UDI_MINOR_NODES); - udi_initialised = 0; - return 0; -} - -int slsi_udi_node_init(struct slsi_dev *sdev, struct device *parent) -{ - return slsi_cdev_create(sdev, parent); -} - -int slsi_udi_node_deinit(struct slsi_dev *sdev) -{ - slsi_cdev_destroy(sdev); - return 0; -} diff --git a/drivers/net/wireless/scsc/udi.h b/drivers/net/wireless/scsc/udi.h deleted file mode 100644 index 114b809c799e..000000000000 --- a/drivers/net/wireless/scsc/udi.h +++ /dev/null @@ -1,31 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef __SLSI_UDI_H__ -#define __SLSI_UDI_H__ - -#include "dev.h" - -#ifdef SLSI_TEST_DEV - -/* Maximum number of nodes supported in UNIT TEST MODE - * arbitrarily set to 20, could increase this if needed - */ -#define SLSI_UDI_MINOR_NODES 20 - -#else -#define SLSI_UDI_MINOR_NODES 2 /* Maximum number of nodes supported. */ -#endif - -int slsi_udi_node_init(struct slsi_dev *sdev, struct device *parent); -int slsi_udi_node_deinit(struct slsi_dev *sdev); - -int slsi_udi_init(void); -int slsi_udi_deinit(void); -int slsi_kernel_to_user_space_event(struct slsi_log_client *log_client, u16 event, u32 data_length, const u8 *data); -int slsi_check_cdev_refs(void); - -#endif diff --git a/drivers/net/wireless/scsc/unifiio.h b/drivers/net/wireless/scsc/unifiio.h deleted file mode 100644 index d5cb1c091e13..000000000000 --- a/drivers/net/wireless/scsc/unifiio.h +++ /dev/null @@ -1,455 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd and its Licensors. - * All rights reserved. - * - *****************************************************************************/ - -#ifndef __UNIFIIO_H__ -#define __UNIFIIO_H__ - -#include -/* The following include of linux/if.h is needed to get IFNAMSIZ. - * The conditional include before it is necessary to get the linux/if.h - * include to compile... - */ -#ifdef __KERNEL__ -#include -#include -#else -#include -#include -#endif -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define UNIFI_GET_UDI_ENABLE _IOR('u', 1, int) -#define UNIFI_SET_UDI_ENABLE _IOW('u', 2, int) -/* Values for UDI_ENABLE */ -#define UDI_ENABLE_DATA 0x1 -#define UDI_ENABLE_CONTROL 0x2 - -/* MIB set/get. Arg is a pointer to a varbind */ -#define UNIFI_GET_MIB _IOWR('u', 3, unsigned char) -#define UNIFI_SET_MIB _IOW('u', 4, unsigned char) -#define MAX_MIB_DATA_LENGTH 2048 - -/* Private IOCTLs */ -#define SIOCIWS80211POWERSAVEPRIV SIOCIWFIRSTPRIV -#define SIOCIWG80211POWERSAVEPRIV (SIOCIWFIRSTPRIV + 1) -#define SIOCIWS80211RELOADDEFAULTSPRIV (SIOCIWFIRSTPRIV + 2) -#define SIOCIWSCONFWAPIPRIV (SIOCIWFIRSTPRIV + 4) -#define SIOCIWSWAPIKEYPRIV (SIOCIWFIRSTPRIV + 6) -#define SIOCIWSSMEDEBUGPRIV (SIOCIWFIRSTPRIV + 8) -#define SIOCIWSAPCFGPRIV (SIOCIWFIRSTPRIV + 10) -#define SIOCIWSAPSTARTPRIV (SIOCIWFIRSTPRIV + 12) -#define SIOCIWSAPSTOPPRIV (SIOCIWFIRSTPRIV + 14) -#define SIOCIWSFWRELOADPRIV (SIOCIWFIRSTPRIV + 16) -#define SIOCIWSSTACKSTART (SIOCIWFIRSTPRIV + 18) -#define SIOCIWSSTACKSTOP (SIOCIWFIRSTPRIV + 20) - -#define IWPRIV_POWER_SAVE_MAX_STRING 32 -#define IWPRIV_SME_DEBUG_MAX_STRING 32 -#define IWPRIV_SME_MAX_STRING 120 - -/* Private configuration commands */ -#define UNIFI_CFG _IOWR('u', 5, unsigned char[4]) -/** - * <------------------ Read/Write Buffer --------------------> - * _____________________________________________________________ - * | Cmd | Arg | ... Buffer (opt) ... | - * ------------------------------------------------------------- - * <-- uint --><-- uint --><----- unsigned char buffer ------> - * - * Cmd: A enum unifi_cfg_command command. - * Arg: Out:Length if Cmd==UNIFI_CFG_GET - * In:PowerOnOff if Cmd==UNIFI_CFG_POWER - * In:PowerMode if Cmd==UNIFI_CFG_POWERSAVE - * In:Length if Cmd==UNIFI_CFG_FILTER - * In:WMM Qos Info if Cmd==UNIFI_CFG_WMM_QOS_INFO - * Buffer: Out:Data if Cmd==UNIFI_CFG_GET - * NULL if Cmd==UNIFI_CFG_POWER - * NULL if Cmd==UNIFI_CFG_POWERSAVE - * In:Filters if Cmd==UNIFI_CFG_FILTER - * - * where Filters is a struct uf_cfg_bcast_packet_filter structure - * followed by 0 - n struct tclas structures. The length of the struct tclas - * structures is obtained by struct uf_cfg_bcast_packet_filter::tclas_ies_length. - */ - -#define UNIFI_BUILD_TYPE _IOWR('u', 7, unsigned char) - -#define UNIFI_BUILD_NME 1 -#define UNIFI_BUILD_WEXT 2 -#define UNIFI_BUILD_AP 3 - -/* debugging */ -#define UNIFI_SET_DEBUG _IO('u', 0x11) -#define UNIFI_SET_TRACE _IO('u', 0x12) - -#define UNIFI_GET_INIT_STATUS _IOR('u', 0x15, int) -#define UNIFI_SET_UDI_LOG_CONFIG _IOR('u', 0x16, struct unifiio_udi_config_t) -#define UNIFI_SET_UDI_LOG_MASK _IOR('u', 0x18, struct unifiio_filter_t) - -#define UNIFI_INIT_HW _IOR('u', 0x13, unsigned char) -#define UNIFI_INIT_NETDEV _IOW('u', 0x14, unsigned char[6]) -#define UNIFI_SME_PRESENT _IOW('u', 0x19, int) - -#define UNIFI_CFG_PERIOD_TRAFFIC _IOW('u', 0x21, unsigned char[4]) -#define UNIFI_CFG_UAPSD_TRAFFIC _IOW('u', 0x22, unsigned char) - -#define UNIFI_SOFTMAC_CFG _IOWR('u', 0x30, unsigned char[4]) - -#define UNIFI_NETDEV_CFG _IOWR('u', 0x31, struct unifiio_netdev_cfg_t) -#define UNIFI_STREAM_CFG _IOWR('u', 0x32, struct unifiio_stream_cfg_t) -#define UNIFI_AMSDU_CFG _IOWR('u', 0x33, struct unifiio_amsdu_cfg_t) -#define UNIFI_BA_CFG _IOWR('u', 0x34, struct unifiio_ba_cfg_t) -#define UNIFI_SUSPEND_RESUME_CFG _IOWR('u', 0x35, struct unifiio_suspend_resume_cfg_t) -#define UNIFI_SRC_SINK_IOCTL _IOWR('u', 0x41, struct unifiio_src_sink_arg_t) - -#define src_sink_action uint16_t -#define SRC_SINK_ACTION_NONE ((src_sink_action)0x0000) -#define SRC_SINK_ACTION_ENABLE_BA ((src_sink_action)0x0001) -#define SRC_SINK_ACTION_SINK_START ((src_sink_action)0x0002) -#define SRC_SINK_ACTION_SINK_STOP ((src_sink_action)0x0003) -#define SRC_SINK_ACTION_GEN_START ((src_sink_action)0x0004) -#define SRC_SINK_ACTION_GEN_STOP ((src_sink_action)0x0005) -#define SRC_SINK_ACTION_SINK_REPORT ((src_sink_action)0x0006) -#define SRC_SINK_ACTION_GEN_REPORT ((src_sink_action)0x0007) -#define SRC_SINK_ACTION_SINK_REPORT_CACHED ((src_sink_action)0x0008) -#define SRC_SINK_ACTION_GEN_REPORT_CACHED ((src_sink_action)0x0009) -#define SRC_SINK_ACTION_LOOPBACK_START ((src_sink_action)0x000A) -#define SRC_SINK_ACTION_LOOPBACK_STOP ((src_sink_action)0x000B) - -#define src_sink_direction uint16_t -#define SRC_SINK_DIRECTION_TX ((src_sink_direction)0x0000) -#define SRC_SINK_DIRECTION_RX ((src_sink_direction)0x0001) - -#define src_sink_endpoint uint16_t -#define SRC_SINK_ENDPOINT_HOSTIO ((src_sink_endpoint)0x0000) -#define SRC_SINK_ENDPOINT_MACRAME ((src_sink_endpoint)0x0001) - -struct unifiio_src_sink_report { - /* total reporting time requested by the user in seconds*/ - uint32_t time; - /* requested report interval in microseconds */ - uint32_t interval; - - /* timestamp [jiffies in millisec] for each report returned by the driver */ - uint32_t timestamp; - /* actual interval used for the report calculations from the firmware */ - uint32_t duration; - /* number of packets during the above duration */ - uint32_t count; - /* number of octets during the above duration */ - uint32_t octet; - /* throughput in kbps */ - uint32_t kbps; - /* CPU idle ratios */ - uint16_t idle_ratio; - uint16_t interrupt_latency; - uint16_t free_kbytes; - /* only relevant for SRC a.k.a GEN mode */ - uint32_t failed_count; -}; - -/* fields specific to SRC a.k.a GEN IOCTLs */ -struct unifiio_src_sink_gen_config { - uint16_t size; - uint16_t use_streaming; - uint16_t pkts_per_intr; - uint32_t ipv4_dest; -}; - -/* fields specific to SRC/SINK CONFIG IOCTLs */ -struct unifiio_src_sink_config { - uint32_t interval; - uint16_t pkts_per_int; - union { - struct unifiio_src_sink_gen_config gen; - } u; -}; - -/* fields common to SRC/SINK IOCTLs */ -struct unifiio_src_sink_common { - /* one of SRC_SINK_ACTION_* for driver IOCTL */ - src_sink_action action; - uint16_t vif; - src_sink_direction direction; - src_sink_endpoint endpoint; -}; - -struct unifiio_src_sink_arg_t { - /* arg in */ - struct unifiio_src_sink_common common; - union { - struct unifiio_src_sink_config config; - struct unifiio_src_sink_report report; - } u; -}; - -/* Structure of data read from the unifi device. */ -struct udi_msg_t { - /* Length (in bytes) of entire structure including appended bulk data */ - int length; - - /* System time (in milliseconds) that signal was transferred */ - int timestamp; - - /* Direction in which signal was transferred. */ - int direction; -#define UDI_FROM_HOST 0 -#define UDI_TO_HOST 1 -#define UDI_CONFIG_IND 2 - - /* The length of the signal (in bytes) not including bulk data */ - int signal_length; - - /* Signal body follows, then any bulk data */ -}; - -/* Add these to the filter signal_ids to enable partial filtering of the MA_UNITDATA Data - * the top bit is set to indicate this is not a HIP Signal ID but a special Filter - */ -#define UDI_MA_UNITDATA_FILTER_ALLOW_MASK 0x8000 /* Filter MA_UNITDATA_REQ and MA_UNITDATA_IND */ -#define UDI_MA_UNITDATA_FILTER_ALLOW_MGT_ID 0x8001 /* Filter MA_UNITDATA_REQ and MA_UNITDATA_IND but Log management Frames */ -#define UDI_MA_UNITDATA_FILTER_ALLOW_KEY_ID 0x8002 /* Filter MA_UNITDATA_REQ and MA_UNITDATA_IND but Log Key Data Frames (Arp, Eapol, Dhcp etc) */ -#define UDI_MA_UNITDATA_FILTER_ALLOW_CFM_ERROR_ID 0x8004 /* Filter MA_UNITDATA_CFM but MA_UNITDATA_CFM(error) */ -#define UDI_MA_UNITDATA_FILTER_ALLOW_EAPOL_ID 0x8008 /* Filter MA_UNITDATA_REQ and MA_UNITDATA_IND but Log Eapol data */ - -/** - * Signals used to indicate to user space that the kernel module has been - * unloaded. The user space applications can based on this indication determine - * if they should unregister from the char device. - */ -#define UDI_DRV_SIGNAL_BASE 0xA000 -#define UDI_DRV_UNLOAD_IND (UDI_DRV_SIGNAL_BASE + 1) -#define UDI_DRV_DROPPED_FRAMES (UDI_DRV_SIGNAL_BASE + 2) -#define UDI_DRV_DROPPED_DATA_FRAMES (UDI_DRV_SIGNAL_BASE + 3) -#define UDI_DRV_SUSPEND_IND (UDI_DRV_SIGNAL_BASE + 4) -#define UDI_DRV_RESUME_IND (UDI_DRV_SIGNAL_BASE + 5) - -struct unifiio_udi_config_t { - uint16_t ma_unitdata_size_limit; /* if non-zero, the MA_UNITDATA_REQ and MA_UNITDATA_IND are capped by this size */ -}; - -struct unifiio_filter_t { - uint16_t log_listed_flag; /* if non-zero, log listed sigs and ignore others (otherwise vice versa) */ - uint16_t signal_ids_n; /* Number of elements in signal_ids[] */ - uint16_t signal_ids[5]; /* list of the signals to log */ -}; - -#define unifi_cfg_command uint32_t -#define UNIFI_CFG_GET ((unifi_cfg_command)0) -#define UNIFI_CFG_POWER ((unifi_cfg_command)1) -#define UNIFI_CFG_POWERSAVE ((unifi_cfg_command)2) -#define UNIFI_CFG_FILTER ((unifi_cfg_command)3) -#define UNIFI_CFG_POWERSUPPLY ((unifi_cfg_command)4) -#define UNIFI_CFG_WMM_QOSINFO ((unifi_cfg_command)5) -#define UNIFI_CFG_WMM_ADDTS ((unifi_cfg_command)6) -#define UNIFI_CFG_WMM_DELTS ((unifi_cfg_command)7) -#define UNIFI_CFG_STRICT_DRAFT_N ((unifi_cfg_command)8) -#define UNIFI_CFG_SET_AP_CONFIG ((unifi_cfg_command)9) -#define UNIFI_CFG_CORE_DUMP ((unifi_cfg_command)10) - -#define unifi_cfg_power uint32_t -#define UNIFI_CFG_POWER_UNSPECIFIED ((unifi_cfg_power)0) -#define UNIFI_CFG_POWER_OFF ((unifi_cfg_power)1) -#define UNIFI_CFG_POWER_ON ((unifi_cfg_power)2) - -#define unifi_cfg_powersupply uint32_t -#define UNIFI_CFG_POWERSUPPLY_UNSPECIFIED ((unifi_cfg_powersupply)0) -#define UNIFI_CFG_POWERSUPPLY_MAINS ((unifi_cfg_powersupply)1) -#define UNIFI_CFG_POWERSUPPLY_BATTERIES ((unifi_cfg_powersupply)2) - -#define unifi_cfg_powersave uint32_t -#define UNIFI_CFG_POWERSAVE_UNSPECIFIED ((unifi_cfg_powersave)0) -#define UNIFI_CFG_POWERSAVE_NONE ((unifi_cfg_powersave)1) -#define UNIFI_CFG_POWERSAVE_FAST ((unifi_cfg_powersave)2) -#define UNIFI_CFG_POWERSAVE_FULL ((unifi_cfg_powersave)3) -#define UNIFI_CFG_POWERSAVE_AUTO ((unifi_cfg_powersave)4) - -#define unifi_cfg_get uint32_t -#define UNIFI_CFG_GET_COEX ((unifi_cfg_get)0) -#define UNIFI_CFG_GET_POWER_MODE ((unifi_cfg_get)1) -#define UNIFI_CFG_GET_VERSIONS ((unifi_cfg_get)2) -#define UNIFI_CFG_GET_POWER_SUPPLY ((unifi_cfg_get)3) -#define UNIFI_CFG_GET_INSTANCE ((unifi_cfg_get)4) -#define UNIFI_CFG_GET_AP_CONFIG ((unifi_cfg_get)5) - -#define UNIFI_CFG_FILTER_NONE 0x0000 -#define UNIFI_CFG_FILTER_DHCP 0x0001 -#define UNIFI_CFG_FILTER_ARP 0x0002 -#define UNIFI_CFG_FILTER_NBNS 0x0004 -#define UNIFI_CFG_FILTER_NBDS 0x0008 -#define UNIFI_CFG_FILTER_CUPS 0x0010 -#define UNIFI_CFG_FILTER_ALL 0xFFFF - -#define uf_cfg_packet_filter_type uint32_t -#define UNIFI_CFG_FILTER_TYPE_NONE ((uf_cfg_packet_filter_type)0) -#define UNIFI_CFG_FILTER_TYPE_ACTIVE_HOST ((uf_cfg_packet_filter_type)1) -#define UNIFI_CFG_FILTER_TYPE_SUSPENDED_HOST ((uf_cfg_packet_filter_type)2) - -struct uf_cfg_bcast_packet_filter { - unsigned long filter_mode; /* as defined by HIP protocol */ - uf_cfg_packet_filter_type packet_filter_type; - unsigned char arp_filter; - unsigned char dhcp_filter; - unsigned long tclas_ies_length; /* length of tclas_ies in bytes */ - unsigned char tclas_ies[1]; /* variable length depending on above field */ -}; - -struct uf_cfg_ap_config { - uint8_t phySupportedBitmap; - uint8_t channel; - uint16_t beaconInterval; - uint8_t dtimPeriod; - bool wmmEnabled; - uint8_t shortSlotTimeEnabled; - uint16_t groupkeyTimeout; - bool strictGtkRekeyEnabled; - uint16_t gmkTimeout; - uint16_t responseTimeout; - uint8_t retransLimit; - uint8_t rxStbc; - bool rifsModeAllowed; - uint8_t dualCtsProtection; - uint8_t ctsProtectionType; - uint16_t maxListenInterval; -}; - -struct csr_wifi_cfg_coex_info { - bool hasTrafficData; - uint8_t currentTrafficType; - uint16_t currentPeriodMs; - uint8_t currentPowerSave; - uint16_t currentCoexPeriodMs; - uint16_t currentCoexLatencyMs; - bool hasBtDevice; - uint32_t currentBlackOutDurationUs; - uint32_t currentBlackOutPeriodUs; - uint8_t currentCoexScheme; -}; - -struct tcpip_clsfr { - __u8 cls_fr_type; - __u8 cls_fr_mask; - __u8 version; - __u8 source_ip_addr[4]; - __u8 dest_ip_addr[4]; - __u16 source_port; - __u16 dest_port; - __u8 dscp; - __u8 protocol; - __u8 reserved; -} __packed; -#define tcpip_clsfr_t struct tcpip_clsfr - -struct tclas { - __u8 element_id; - __u8 length; - __u8 user_priority; - tcpip_clsfr_t tcp_ip_cls_fr; -} __packed; - -#define CONFIG_IND_ERROR 0x01 -#define CONFIG_IND_EXIT 0x02 -#define CONFIG_SME_NOT_PRESENT 0x10 -#define CONFIG_SME_PRESENT 0x20 - -/* This is used by the UNIFI_NETDEV_CFG ioctl which is a Multi-netdev replacement for - * UNIFI_INIT_NETDEV. The all netdev are created statically and can be mapped/registered - * to a particular vif_index/MAC address/interface mode dynamically using this call. - * - * Configure operations (operation == 0): - * - * Attempting to operate on a negative interfaceTag is an attempt to - * create a NEW netdevice.A valid vif_index and macaddr must be supplied. - * interfaceMode will not be checked. The new interfaceTag and name will be - * copied back on success. - * - * Using an interfaceTag >=0 attempts to reconfigure an existing netdevice. The new - * vif_index, macaddr and interfaceMode will be applied if all is valid. Setting a - * vif_index of zero causes the given netdevice to be unregistered instead. - * The contents of the name[] field will be ignored as input, and the existing - * interface name copied back as output. - * - * Query operations (operation == 1): - * - * The first identifying field with a potentially valid value will be used to - * identify an interface, and if a match is found its values will be copied back - * into the structure and returned to the user. The fields are checked in this order: - * - * interfaceTag (valid if >= 0) - * vif_index (valid if non-zero) - * name (valid if first byte non-zero) - * macaddr (valid if not broadcast) - */ -struct unifiio_netdev_cfg_t { - uint8_t operation; /* 0 = configure, 1 = query */ - /* All other fields potentially bidirectional */ - int interfaceTag; /* <0 => create new, >=0 => reconfigure existing */ - uint8_t vif_index; /* VIF index to use (0 => remove netdev) */ - uint8_t interfaceMode; /* Values defined in csr_wifi_router_ctrl_prim.h */ - unsigned char macaddr[6]; /* MAC address */ - char name[IFNAMSIZ]; /* Interface name */ - unsigned char peer_macaddr[6]; /* peer MAC address */ - uint16_t association_id; /* Associate ID used for the peer */ -}; - -#define unifiio_stream_cfg_operation_type uint32_t -#define UNIFI_CFG_STREAM_OPERATION_TYPE_NONE ((unifiio_stream_cfg_operation_type)0) -#define UNIFI_CFG_STREAM_OPERATION_TYPE_CREATE ((unifiio_stream_cfg_operation_type)1) -#define UNIFI_CFG_STREAM_OPERATION_TYPE_STOP ((unifiio_stream_cfg_operation_type)2) -#define UNIFI_CFG_STREAM_OPERATION_TYPE_DELETE ((unifiio_stream_cfg_operation_type)3) - -struct unifiio_stream_cfg_t { - unifiio_stream_cfg_operation_type operation; - int interfaceTag; /* A valid interface tag */ - unsigned char peer_macaddr[6]; /* Peer STA MAC address */ - uint16_t tId; /* Traffic identifier user priority */ - uint16_t handle; /* Handle as indicated in MA-stream.indication */ - uint16_t size; /* Size as indicated in MA-stream.indication */ -}; - -#define unifiio_amsdu_cfg_operation_type uint32_t -#define UNIFI_CFG_AMSDU_OPERATION_TYPE_SET_MAX_SIZE ((unifiio_amsdu_cfg_operation_type)0) - -struct unifiio_amsdu_cfg_t { - unifiio_amsdu_cfg_operation_type operation; - int interfaceTag; /* A valid interface tag */ - unsigned char peer_macaddr[6]; /* Peer STA MAC address */ - uint16_t size; /* Maximum A-MSDU length for peer obtained from HT element */ -}; - -#define unifiio_ba_cfg_operation_type uint32_t -#define UNIFI_CFG_BA_SESSION_STOP ((unifiio_ba_cfg_operation_type)0) -#define UNIFI_CFG_BA_SESSION_START ((unifiio_ba_cfg_operation_type)1) - -struct unifiio_ba_cfg_t { - unifiio_ba_cfg_operation_type operation; - int interfaceTag; /* A valid interface tag */ - unsigned char peer_macaddr[6]; /* Peer STA MAC address */ - uint16_t tId; /* Traffic identifier */ - uint8_t role; /* Role - 0: originator, 1 - recipient */ - uint16_t window_size; /* Window size as negotiated in BA establish */ - uint16_t ssn; /* Starting sequence number as negotiated in BA establish */ -}; - -#define unifiio_suspend_resume_cfg_operation_type uint32_t -#define UNIFI_CFG_SUSPEND ((unifiio_suspend_resume_cfg_operation_type)0) -#define UNIFI_CFG_RESUME ((unifiio_suspend_resume_cfg_operation_type)1) -#define UNIFI_CFG_WAIT_FOR_RESUME ((unifiio_suspend_resume_cfg_operation_type)2) - -struct unifiio_suspend_resume_cfg_t { - unifiio_suspend_resume_cfg_operation_type operation; - unsigned timeout_ms; /* used with UNIFI_CFG_WAIT_FOR_RESUME only */ -}; - -#ifdef __cplusplus -} -#endif -#endif /* __UNIFIIO_H__ */ diff --git a/drivers/net/wireless/scsc/utils.h b/drivers/net/wireless/scsc/utils.h deleted file mode 100755 index 278a759ab9f9..000000000000 --- a/drivers/net/wireless/scsc/utils.h +++ /dev/null @@ -1,655 +0,0 @@ -/****************************************************************************** - * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef SLSI_UTILS_H__ -#define SLSI_UTILS_H__ - -#include -#include -#include -#include -#include -#include - -#include "netif.h" -#include "wakelock.h" -#ifdef CONFIG_SCSC_SMAPPER -struct slsi_skb_cb { - u32 sig_length; - u32 data_length; - u32 frame_format; - u32 colour; - bool free_ma_unitdat; - struct sk_buff *skb_addr; -}; - -static inline struct slsi_skb_cb *slsi_skb_cb_get(struct sk_buff *skb) -{ - return (struct slsi_skb_cb *)skb->cb; -} - -static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb) -{ - BUILD_BUG_ON(sizeof(struct slsi_skb_cb) > sizeof(skb->cb)); - - memset(skb->cb, 0, sizeof(struct slsi_skb_cb)); - return slsi_skb_cb_get(skb); -} -#endif - -static inline u32 slsi_convert_tlv_data_to_value(u8 *data, u16 length) -{ - u32 value = 0; - int i; - - if (length > 4) - return 0; - for (i = 0; i < length; i++) - value |= ((u32)data[i]) << i * 8; - - return value; -} - -#ifdef __cplusplus -extern "C" { -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) -#define SLSI_ETHER_COPY(dst, src) ether_addr_copy((dst), (src)) -#define SLSI_ETHER_EQUAL(mac1, mac2) ether_addr_equal((mac1), (mac2)) -#else -#define SLSI_ETHER_COPY(dst, src) memcpy((dst), (src), ETH_ALEN) -#define SLSI_ETHER_EQUAL(mac1, mac2) (memcmp((mac1), (mac2), ETH_ALEN) == 0) -#endif - -extern uint slsi_sg_host_align_mask; -#define SLSI_HIP_FH_SIG_PREAMBLE_LEN 4 -#define SLSI_SKB_GET_ALIGNMENT_OFFSET(skb) (0) - -/* Get the Compiler to ignore Unused parameters */ -#define SLSI_UNUSED_PARAMETER(x) ((void)(x)) - -/* Helper ERROR Macros */ -#define SLSI_ECR(func) \ - do { \ - int _err = (func); \ - if (_err != 0) { \ - SLSI_ERR_NODEV("e=%d\n", _err); \ - return _err; \ - } \ - } while (0) - -#define SLSI_EC(func) \ - do { \ - int _err = (func); \ - if (_err != 0) { \ - SLSI_ERR_NODEV("e=%d\n", _err); \ - return; \ - } \ - } while (0) - -#define SLSI_EC_GOTO(func, err, label) \ - do { \ - (err) = func; \ - if ((err) != 0) { \ - WARN_ON(1); \ - SLSI_ERR(sdev, "fail at line:%d\n", __LINE__); \ - goto label; \ - } \ - } while (0) - -/*------------------------------------------------------------------*/ -/* Endian conversion */ -/*------------------------------------------------------------------*/ -#define SLSI_BUFF_LE_TO_U16(ptr) (((u16)((u8 *)(ptr))[0]) | ((u16)((u8 *)(ptr))[1]) << 8) -#define SLSI_U16_TO_BUFF_LE(uint, ptr) \ - do { \ - u32 local_uint_tmp = (uint); \ - ((u8 *)(ptr))[0] = ((u8)((local_uint_tmp & 0x00FF))); \ - ((u8 *)(ptr))[1] = ((u8)(local_uint_tmp >> 8)); \ - } while (0) - -#define SLSI_U32_TO_BUFF_LE(uint, ptr) ((*(u32 *)ptr) = cpu_to_le32(uint)) - -#define SLSI_BUFF_LE_TO_U16_P(output, input) \ - do { \ - (output) = (u16)((((u16)(input)[1]) << 8) | ((u16)(input)[0])); \ - (input) += 2; \ - } while (0) - -#define SLSI_BUFF_LE_TO_U32_P(output, input) \ - do { \ - (output) = le32_to_cpu(*(u32 *)input); \ - (input) += 4; \ - } while (0) - -#define SLSI_U16_TO_BUFF_LE_P(output, input) \ - do { \ - (output)[0] = ((u8)((input) & 0x00FF)); \ - (output)[1] = ((u8)((input) >> 8)); \ - (output) += 2; \ - } while (0) - -#define SLSI_U32_TO_BUFF_LE_P(output, input) \ - do { \ - (*(u32 *)output) = cpu_to_le32(input); \ - (output) += 4; \ - } while (0) - -#ifdef CONFIG_SCSC_WLAN_SKB_TRACKING -void slsi_dbg_track_skb_init(void); -void slsi_dbg_track_skb_reset(void); -void slsi_dbg_track_skb_f(struct sk_buff *skb, gfp_t flags, const char *file, int line); -bool slsi_dbg_untrack_skb_f(struct sk_buff *skb, const char *file, int line); -bool slsi_dbg_track_skb_marker_f(struct sk_buff *skb, const char *file, int line); -#define slsi_dbg_track_skb(skb_, flags_) slsi_dbg_track_skb_f(skb_, flags_, __FILE__, __LINE__) -#define slsi_dbg_untrack_skb(skb_) slsi_dbg_untrack_skb_f(skb_, __FILE__, __LINE__) -#define slsi_dbg_track_skb_marker(skb_) slsi_dbg_track_skb_marker_f(skb_, __FILE__, __LINE__) -void slsi_dbg_track_skb_report(void); - -static inline struct sk_buff *slsi_dev_alloc_skb_f(unsigned int length, const char *file, int line) -{ - struct sk_buff *skb = dev_alloc_skb(SLSI_NETIF_SKB_HEADROOM + SLSI_NETIF_SKB_TAILROOM + length); - - if (skb) { -#ifdef CONFIG_SCSC_SMAPPER - slsi_skb_cb_init(skb); -#endif - skb_reserve(skb, SLSI_NETIF_SKB_HEADROOM - SLSI_SKB_GET_ALIGNMENT_OFFSET(skb)); - slsi_dbg_track_skb_f(skb, GFP_ATOMIC, file, line); - } - return skb; -} - -static inline struct sk_buff *slsi_alloc_skb_f(unsigned int size, gfp_t priority, const char *file, int line) -{ - struct sk_buff *skb = alloc_skb(size, priority); - - if (skb) { -#ifdef CONFIG_SCSC_SMAPPER - slsi_skb_cb_init(skb); -#endif - slsi_dbg_track_skb_f(skb, priority, file, line); - } - - return skb; -} - -static inline struct sk_buff *slsi_alloc_skb_headroom_f(unsigned int size, gfp_t priority, const char *file, int line) -{ - struct sk_buff *skb = alloc_skb(SLSI_NETIF_SKB_HEADROOM + SLSI_NETIF_SKB_TAILROOM + size, priority); - - if (skb) { -#ifdef CONFIG_SCSC_SMAPPER - slsi_skb_cb_init(skb); -#endif - skb_reserve(skb, SLSI_NETIF_SKB_HEADROOM - SLSI_SKB_GET_ALIGNMENT_OFFSET(skb)); - slsi_dbg_track_skb_f(skb, priority, file, line); - } - return skb; -} - -static inline void slsi_skb_unlink_f(struct sk_buff *skb, struct sk_buff_head *list, const char *file, int line) -{ - skb_unlink(skb, list); - slsi_dbg_track_skb_marker_f(skb, file, line); -} - -static inline void slsi_skb_queue_tail_f(struct sk_buff_head *list, struct sk_buff *skb, const char *file, int line) -{ - skb_queue_tail(list, skb); - slsi_dbg_track_skb_marker_f(skb, file, line); -} - -static inline void slsi_skb_queue_head_f(struct sk_buff_head *list, struct sk_buff *skb, const char *file, int line) -{ - skb_queue_head(list, skb); - slsi_dbg_track_skb_marker_f(skb, file, line); -} - -static inline struct sk_buff *slsi_skb_dequeue_f(struct sk_buff_head *list, const char *file, int line) -{ - struct sk_buff *skb = skb_dequeue(list); - - if (skb) - slsi_dbg_track_skb_marker_f(skb, file, line); - return skb; -} - -static inline struct sk_buff *slsi_skb_realloc_headroom_f(struct sk_buff *skb, unsigned int headroom, const char *file, int line) -{ - skb = skb_realloc_headroom(skb, headroom); - if (skb) { -#ifdef CONFIG_SCSC_SMAPPER - slsi_skb_cb_init(skb); -#endif - slsi_dbg_track_skb_f(skb, GFP_ATOMIC, file, line); - } - return skb; -} - -static inline struct sk_buff *slsi_skb_copy_f(struct sk_buff *skb, gfp_t priority, const char *file, int line) -{ - skb = skb_copy(skb, priority); - - if (skb) - slsi_dbg_track_skb_f(skb, priority, file, line); - return skb; -} - -static inline struct sk_buff *skb_copy_expand_f(struct sk_buff *skb, int newheadroom, int newtailroom, gfp_t priority, const char *file, int line) -{ - skb = skb_copy_expand(skb, newheadroom, newtailroom, priority); - - if (skb) - slsi_dbg_track_skb_f(skb, priority, file, line); - return skb; -} - -static inline struct sk_buff *slsi_skb_clone_f(struct sk_buff *skb, gfp_t priority, const char *file, int line) -{ - skb = skb_clone(skb, priority); - - if (skb) - slsi_dbg_track_skb_f(skb, priority, file, line); - return skb; -} - -static inline void slsi_kfree_skb_f(struct sk_buff *skb, const char *file, int line) -{ - /* If untrack fails we do not free the SKB - * This helps tracking bad pointers and double frees - */ -#ifdef CONFIG_SCSC_SMAPPER - struct slsi_skb_cb *cb; - - if (!skb) - return; - - cb = (struct slsi_skb_cb *)skb->cb; - - if (cb && !cb->free_ma_unitdat && cb->skb_addr && slsi_dbg_untrack_skb_f(cb->skb_addr, file, line)) { - kfree_skb(cb->skb_addr); - cb->skb_addr = NULL; - } -#endif - if (slsi_dbg_untrack_skb_f(skb, file, line)) - kfree_skb(skb); -} - -#define slsi_dev_alloc_skb(length_) slsi_dev_alloc_skb_f(length_, __FILE__, __LINE__) -#define slsi_alloc_skb(size_, priority_) slsi_alloc_skb_f(size_, priority_, __FILE__, __LINE__) -#define slsi_alloc_skb_headroom(size_, priority_) slsi_alloc_skb_headroom_f(size_, priority_, __FILE__, __LINE__) -#define slsi_skb_realloc_headroom(skb_, headroom_) slsi_skb_realloc_headroom_f(skb_, headroom_, __FILE__, __LINE__) -#define slsi_skb_copy(skb_, priority_) slsi_skb_copy_f(skb_, priority_, __FILE__, __LINE__) -#define slsi_skb_copy_expand(skb_, newheadroom_, newtailroom_, priority_) skb_copy_expand_f(skb_, newheadroom_, newtailroom_, priority_, __FILE__, __LINE__) -#define slsi_skb_clone(skb_, priority_) slsi_skb_clone_f(skb_, priority_, __FILE__, __LINE__) -#define slsi_kfree_skb(skb_) slsi_kfree_skb_f(skb_, __FILE__, __LINE__) -#define slsi_skb_unlink(skb_, list_) slsi_skb_unlink_f(skb_, list_, __FILE__, __LINE__) -#define slsi_skb_queue_tail(list_, skb_) slsi_skb_queue_tail_f(list_, skb_, __FILE__, __LINE__) -#define slsi_skb_queue_head(list_, skb_) slsi_skb_queue_head_f(list_, skb_, __FILE__, __LINE__) -#define slsi_skb_dequeue(list_) slsi_skb_dequeue_f(list_, __FILE__, __LINE__) - -static inline void slsi_skb_queue_purge(struct sk_buff_head *list) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(list)) != NULL) - slsi_kfree_skb(skb); -} - -#else -#define slsi_dbg_track_skb_init() -#define slsi_dbg_track_skb_reset() -#define slsi_dbg_track_skb(skb_, flags_) -#define slsi_dbg_untrack_skb(skb_) -#define slsi_dbg_track_skb_marker(skb_) -#define slsi_dbg_track_skb_report() - -static inline struct sk_buff *slsi_dev_alloc_skb_f(unsigned int length, const char *file, int line) -{ - struct sk_buff *skb = dev_alloc_skb(SLSI_NETIF_SKB_HEADROOM + SLSI_NETIF_SKB_TAILROOM + length); - - SLSI_UNUSED_PARAMETER(file); - SLSI_UNUSED_PARAMETER(line); - if (skb) { -#ifdef CONFIG_SCSC_SMAPPER - slsi_skb_cb_init(skb); -#endif - skb_reserve(skb, SLSI_NETIF_SKB_HEADROOM - SLSI_SKB_GET_ALIGNMENT_OFFSET(skb)); - } - return skb; -} - -static inline struct sk_buff *slsi_alloc_skb_f(unsigned int size, gfp_t priority, const char *file, int line) -{ - struct sk_buff *skb = alloc_skb(size, priority); - - SLSI_UNUSED_PARAMETER(file); - SLSI_UNUSED_PARAMETER(line); -#ifdef CONFIG_SCSC_SMAPPER - if (skb) - slsi_skb_cb_init(skb); -#endif - return skb; -} - -static inline struct sk_buff *slsi_alloc_skb_headroom_f(unsigned int size, gfp_t priority, const char *file, int line) -{ - struct sk_buff *skb = alloc_skb(SLSI_NETIF_SKB_HEADROOM + SLSI_NETIF_SKB_TAILROOM + size, priority); - - SLSI_UNUSED_PARAMETER(file); - SLSI_UNUSED_PARAMETER(line); - - if (skb) { -#ifdef CONFIG_SCSC_SMAPPER - slsi_skb_cb_init(skb); -#endif - skb_reserve(skb, SLSI_NETIF_SKB_HEADROOM - SLSI_SKB_GET_ALIGNMENT_OFFSET(skb)); - } - return skb; -} - -static inline void slsi_kfree_skb_f(struct sk_buff *skb) -{ - /* If untrack fails we do not free the SKB - * This helps tracking bad pointers and double frees - */ -#ifdef CONFIG_SCSC_SMAPPER - struct slsi_skb_cb *cb; - - if (!skb) - return; - - cb = (struct slsi_skb_cb *)skb->cb; - - if (cb && !cb->free_ma_unitdat && cb->skb_addr) { - kfree_skb(cb->skb_addr); - cb->skb_addr = NULL; - } -#endif - kfree_skb(skb); -} - -#define slsi_dev_alloc_skb(length_) slsi_dev_alloc_skb_f(length_, __FILE__, __LINE__) -#define slsi_alloc_skb(size_, priority_) slsi_alloc_skb_f(size_, priority_, __FILE__, __LINE__) -#define slsi_alloc_skb_headroom(size_, priority_) slsi_alloc_skb_headroom_f(size_, priority_, __FILE__, __LINE__) -#define slsi_skb_realloc_headroom(skb_, headroom_) skb_realloc_headroom(skb_, headroom_) -#define slsi_skb_copy(skb_, priority_) skb_copy(skb_, priority_) -#define slsi_skb_copy_expand(skb_, newheadroom_, newtailroom_, priority_) skb_copy_expand(skb_, newheadroom_, newtailroom_, priority_) -#define slsi_skb_clone(skb_, priority_) skb_clone(skb_, priority_) -#define slsi_kfree_skb(skb_) slsi_kfree_skb_f(skb_) -#define slsi_skb_unlink(skb_, list_) skb_unlink(skb_, list_) -#define slsi_skb_queue_tail(list_, skb_) skb_queue_tail(list_, skb_) -#define slsi_skb_queue_head(list_, skb_) skb_queue_head(list_, skb_) -#define slsi_skb_dequeue(list_) skb_dequeue(list_) -#define slsi_skb_queue_purge(list_) slsi_skb_queue_purge(list_) - -static inline void slsi_skb_queue_purge(struct sk_buff_head *list) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(list)) != NULL) - slsi_kfree_skb(skb); -} - -#endif - -struct slsi_spinlock { - /* a std spinlock */ - spinlock_t lock; - unsigned long flags; -}; - -/* Spinlock create can't fail, so return success regardless. */ -static inline void slsi_spinlock_create(struct slsi_spinlock *lock) -{ - spin_lock_init(&lock->lock); -} - -static inline void slsi_spinlock_lock(struct slsi_spinlock *lock) -{ - spin_lock_bh(&lock->lock); -} - -static inline void slsi_spinlock_unlock(struct slsi_spinlock *lock) -{ - spin_unlock_bh(&lock->lock); -} - -struct slsi_dev; -struct slsi_skb_work { - struct slsi_dev *sdev; - struct net_device *dev; /* This can be NULL */ - struct workqueue_struct *workqueue; - struct work_struct work; - struct sk_buff_head queue; - void __rcu *sync_ptr; -}; - -static inline int slsi_skb_work_init(struct slsi_dev *sdev, struct net_device *dev, struct slsi_skb_work *work, const char *name, void (*func)(struct work_struct *work)) -{ - rcu_assign_pointer(work->sync_ptr, (void *)sdev); - work->sdev = sdev; - work->dev = dev; - skb_queue_head_init(&work->queue); - INIT_WORK(&work->work, func); - work->workqueue = alloc_ordered_workqueue(name, 0); - - if (!work->workqueue) - return -ENOMEM; - return 0; -} - -static inline void slsi_skb_schedule_work(struct slsi_skb_work *work) -{ - queue_work(work->workqueue, &work->work); -} - -static inline void slsi_skb_work_enqueue_l(struct slsi_skb_work *work, struct sk_buff *skb) -{ - void *sync_ptr; - - rcu_read_lock(); - - sync_ptr = rcu_dereference(work->sync_ptr); - - if (WARN_ON(!sync_ptr)) { - slsi_kfree_skb(skb); - rcu_read_unlock(); - return; - } - skb_queue_tail(&work->queue, skb); - slsi_skb_schedule_work(work); - - rcu_read_unlock(); -} - -static inline struct sk_buff *slsi_skb_work_dequeue_l(struct slsi_skb_work *work) -{ - return skb_dequeue(&work->queue); -} - -static inline void slsi_skb_work_deinit(struct slsi_skb_work *work) -{ - rcu_read_lock(); - - if (WARN_ON(!work->sync_ptr)) { - rcu_read_unlock(); - return; - } - - rcu_assign_pointer(work->sync_ptr, NULL); - rcu_read_unlock(); - - synchronize_rcu(); - flush_workqueue(work->workqueue); - destroy_workqueue(work->workqueue); - work->workqueue = NULL; - slsi_skb_queue_purge(&work->queue); -} - -static inline void slsi_cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) - cfg80211_put_bss(wiphy, bss); -#else - cfg80211_put_bss(bss); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) */ -} - -#ifdef CONFIG_SCSC_WLAN_SKB_TRACKING -static inline void slsi_skb_work_enqueue_f(struct slsi_skb_work *work, struct sk_buff *skb, const char *file, int line) -{ - slsi_dbg_track_skb_marker_f(skb, file, line); - slsi_skb_work_enqueue_l(work, skb); -} - -static inline struct sk_buff *slsi_skb_work_dequeue_f(struct slsi_skb_work *work, const char *file, int line) -{ - struct sk_buff *skb; - - skb = slsi_skb_work_dequeue_l(work); - if (skb) - slsi_dbg_track_skb_marker_f(skb, file, line); - return skb; -} - -#define slsi_skb_work_enqueue(work_, skb_) slsi_skb_work_enqueue_f(work_, skb_, __FILE__, __LINE__) -#define slsi_skb_work_dequeue(work_) slsi_skb_work_dequeue_f(work_, __FILE__, __LINE__) -#else -#define slsi_skb_work_enqueue(work_, skb_) slsi_skb_work_enqueue_l(work_, skb_) -#define slsi_skb_work_dequeue(work_) slsi_skb_work_dequeue_l(work_) -#endif - -static inline void slsi_eth_zero_addr(u8 *addr) -{ - memset(addr, 0x00, ETH_ALEN); -} - -static inline void slsi_eth_broadcast_addr(u8 *addr) -{ - memset(addr, 0xff, ETH_ALEN); -} - -static inline int slsi_str_to_int(char *str, int *result) -{ - int i = 0; - - *result = 0; - if ((str[i] == '-') || ((str[i] >= '0') && (str[i] <= '9'))) { - if (str[0] == '-') - i++; - while (str[i] >= '0' && str[i] <= '9') { - *result *= 10; - *result += (int)str[i++] - '0'; - } - - *result = ((str[0] == '-') ? (-(*result)) : *result); - } - return i; -} - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ -} __packed; - -struct msdu_hdr { - unsigned char da[ETH_ALEN]; - unsigned char sa[ETH_ALEN]; - __be16 length; - struct ieee80211_snap_hdr snap; - __be16 ether_type; -} __packed; - -#define ETHER_TYPE_SIZE 2 -#define MSDU_HLEN sizeof(struct msdu_hdr) -#define MSDU_LENGTH (sizeof(struct ieee80211_snap_hdr) + sizeof(__be16)) - -static inline int slsi_skb_msdu_to_ethhdr(struct sk_buff *skb) -{ - struct ethhdr *eth; - struct msdu_hdr *msdu; - - unsigned char da[ETH_ALEN]; - unsigned char sa[ETH_ALEN]; - __be16 proto; - - msdu = (struct msdu_hdr *)skb->data; - SLSI_ETHER_COPY(da, msdu->da); - SLSI_ETHER_COPY(sa, msdu->sa); - proto = msdu->ether_type; - - skb_pull(skb, MSDU_HLEN); - - eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); - - SLSI_ETHER_COPY(eth->h_dest, da); - SLSI_ETHER_COPY(eth->h_source, sa); - eth->h_proto = proto; - - return 0; -} - -static inline int slsi_skb_ethhdr_to_msdu(struct sk_buff *skb) -{ - struct ethhdr *eth; - struct msdu_hdr *msdu; - unsigned int len; - __be16 ether_type; - - if (skb_headroom(skb) < (MSDU_HLEN - ETH_HLEN)) - return -EINVAL; - - eth = eth_hdr(skb); - ether_type = eth->h_proto; - - len = skb->len; - - skb_pull(skb, ETH_HLEN); - - msdu = (struct msdu_hdr *)skb_push(skb, MSDU_HLEN); - - SLSI_ETHER_COPY(msdu->da, eth->h_dest); - SLSI_ETHER_COPY(msdu->sa, eth->h_source); - msdu->length = htons(len - ETH_HLEN + MSDU_LENGTH); - memcpy(&msdu->snap, rfc1042_header, sizeof(struct ieee80211_snap_hdr)); - msdu->ether_type = ether_type; - - return 0; -} - -static inline u32 slsi_get_center_freq1(struct slsi_dev *sdev, u16 chann_info, u16 center_freq) -{ - u32 center_freq1 = 0x0000; - - SLSI_UNUSED_PARAMETER(sdev); - - switch (chann_info & 0xFF) { - case 40: - center_freq1 = center_freq - 20 * ((chann_info & 0xFF00) >> 8) + 10; - break; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) - case 80: - center_freq1 = center_freq - 20 * ((chann_info & 0xFF00) >> 8) + 30; - break; -#endif - default: - break; - } - return center_freq1; -} - -#ifdef __cplusplus -} -#endif - -#endif /* SLSI_UTILS_H__ */ diff --git a/drivers/net/wireless/scsc/wakelock.c b/drivers/net/wireless/scsc/wakelock.c deleted file mode 100644 index 164f89182549..000000000000 --- a/drivers/net/wireless/scsc/wakelock.c +++ /dev/null @@ -1,117 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd and its Licensors. - * All rights reserved. - * - ****************************************************************************/ -#include -#include -#include "dev.h" -#include "debug.h" -#include "wakelock.h" -#include "utils.h" - -void slsi_wakelock(struct slsi_wake_lock *lock) -{ -#ifdef CONFIG_WAKELOCK - unsigned long flags; - - if (lock == NULL) { - SLSI_ERR_NODEV("Failed to take wakelock, lock is NULL"); - return; - } - spin_lock_irqsave(&lock->wl_spinlock, flags); - if (!lock->counter) - wake_lock(&lock->wl); - - lock->counter++; - spin_unlock_irqrestore(&lock->wl_spinlock, flags); -#else - SLSI_UNUSED_PARAMETER(lock); -#endif -} - -void slsi_wakeunlock(struct slsi_wake_lock *lock) -{ -#ifdef CONFIG_WAKELOCK - unsigned long flags; - - if (lock == NULL) { - SLSI_ERR_NODEV("Failed to unlock the wakelock, lock is NULL"); - return; - } - spin_lock_irqsave(&lock->wl_spinlock, flags); - - if (lock->counter) { - lock->counter--; - if (!lock->counter) - wake_unlock(&lock->wl); - } else { - SLSI_ERR_NODEV("Wakelock has already released!"); - } - spin_unlock_irqrestore(&lock->wl_spinlock, flags); -#else - SLSI_UNUSED_PARAMETER(lock); -#endif -} - -void slsi_wakelock_timeout(struct slsi_wake_lock *lock, int timeout) -{ -#ifdef CONFIG_WAKELOCK - if (lock == NULL) { - SLSI_ERR_NODEV("Failed to take wakelock timeout, lock is NULL"); - return; - } - lock->counter = 1; - wake_lock_timeout(&lock->wl, msecs_to_jiffies(timeout)); -#else - SLSI_UNUSED_PARAMETER(lock); - SLSI_UNUSED_PARAMETER(timeout); -#endif -} - -int slsi_is_wakelock_active(struct slsi_wake_lock *lock) -{ -#ifdef CONFIG_WAKELOCK - if (lock == NULL) { - SLSI_ERR_NODEV("Failed to check wakelock status, lock is NULL"); - return 0; - } - - if (wake_lock_active(&lock->wl)) - return 1; -#else - SLSI_UNUSED_PARAMETER(lock); -#endif - return 0; -} - -void slsi_wakelock_exit(struct slsi_wake_lock *lock) -{ -#ifdef CONFIG_WAKELOCK - if (lock == NULL) { - SLSI_ERR_NODEV("Failed to destroy the wakelock, lock is NULL"); - return; - } - - wake_lock_destroy(&lock->wl); -#else - SLSI_UNUSED_PARAMETER(lock); -#endif -} - -void slsi_wakelock_init(struct slsi_wake_lock *lock, char *name) -{ -#ifdef CONFIG_WAKELOCK - if (lock == NULL) { - SLSI_ERR_NODEV("Failed to init the wakelock, lock is NULL"); - return; - } - lock->counter = 0; - wake_lock_init(&lock->wl, WAKE_LOCK_SUSPEND, name); - spin_lock_init(&lock->wl_spinlock); -#else - SLSI_UNUSED_PARAMETER(lock); - SLSI_UNUSED_PARAMETER(name); -#endif -} diff --git a/drivers/net/wireless/scsc/wakelock.h b/drivers/net/wireless/scsc/wakelock.h deleted file mode 100644 index 1c6a14a4b15f..000000000000 --- a/drivers/net/wireless/scsc/wakelock.h +++ /dev/null @@ -1,31 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. and its Licensors. - * All rights reserved. - * - ****************************************************************************/ - -#ifndef __SLSI_WAKELOCK_H__ -#define __SLSI_WAKELOCK_H__ - -#ifdef CONFIG_WAKELOCK -#include -#endif -#include - -struct slsi_wake_lock { -#ifdef CONFIG_WAKELOCK - struct wake_lock wl; -#endif - /* Spinlock to synchronize the access of the counter */ - spinlock_t wl_spinlock; - int counter; -}; - -void slsi_wakelock(struct slsi_wake_lock *lock); -void slsi_wakeunlock(struct slsi_wake_lock *lock); -void slsi_wakelock_timeout(struct slsi_wake_lock *lock, int timeout); -int slsi_is_wakelock_active(struct slsi_wake_lock *lock); -void slsi_wakelock_exit(struct slsi_wake_lock *lock); -void slsi_wakelock_init(struct slsi_wake_lock *lock, char *name); -#endif diff --git a/drivers/net/wireless/scsc/wl_result.h b/drivers/net/wireless/scsc/wl_result.h deleted file mode 100644 index 2fbcf1124371..000000000000 --- a/drivers/net/wireless/scsc/wl_result.h +++ /dev/null @@ -1,28 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - * WLAN result codes - * - ****************************************************************************/ - -#ifndef WL_RESULT_H__ -#define WL_RESULT_H__ - -#define CsrResult u16 - -#define CSR_RESULT_SUCCESS ((CsrResult)0x0000) -#define CSR_RESULT_FAILURE ((CsrResult)0xffff) - -#define CSR_WIFI_HIP_RESULT_INVALID_VALUE ((CsrResult)1) /* Invalid argument value */ -#define CSR_WIFI_HIP_RESULT_NO_DEVICE ((CsrResult)2) /* The specified device is no longer present */ -#define CSR_WIFI_HIP_RESULT_NO_SPACE ((CsrResult)3) /* A queue or buffer is full */ -#define CSR_WIFI_HIP_RESULT_NO_MEMORY ((CsrResult)4) /* Fatal error, no memory */ -#define CSR_WIFI_HIP_RESULT_RANGE ((CsrResult)5) /* Request exceeds the range of a file or a buffer */ -#define CSR_WIFI_HIP_RESULT_NOT_FOUND ((CsrResult)6) /* A file (typically a f/w patch) is not found */ -#define CSR_WIFI_PS_RESULT_FULL ((CsrResult)7) /* Signal successfully queued, queue now full. */ -#define CSR_WIFI_PS_QSIG_NONE ((CsrResult)8) /* no qsig found, queue empty */ -#define CSR_WIFI_PS_QSIG_NO_SPACE ((CsrResult)9) /* no room for outstanding qsigs */ -#define CSR_WIFI_PS_QS_PAUSED_UNTIL_BOT_UPDATE ((CsrResult)10) /* BOT has disabled the qset and waiting for updates from the firmware */ - -#endif diff --git a/include/scsc/api/asmhcp.h b/include/scsc/api/asmhcp.h deleted file mode 100755 index dfb8cac4e164..000000000000 --- a/include/scsc/api/asmhcp.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/**************************************************************************** - * FILE - * asmhcp.h - ANT Shared Memory Host Controller Protocol - * - * DESCRIPTION - * This file specifies the layout of the ANT Shared Memory - * Host Controller Protocol - */ - -#ifndef __ASMHCP_H__ -#define __ASMHCP_H__ - -#define ASMHCP_TRANSFER_RING_DATA_SIZE (16) -#define ASMHCP_TRANSFER_RING_CMD_SIZE (16) - -#define ASMHCP_BUFFER_SIZE (258) - -struct ASMHCP_TD_CONTROL { - uint16_t length; - uint8_t data[ASMHCP_BUFFER_SIZE]; -}; - -struct ASMHCP_HEADER { - /* AP RW - R4 RO - 64 octets */ - uint32_t magic_value; /* 0x00 */ - uint32_t mailbox_data_ctr_driv_read; /* 0x04 */ - uint32_t mailbox_data_driv_ctr_write; /* 0x08 */ - uint32_t mailbox_cmd_ctr_driv_read; /* 0x0C */ - uint32_t mailbox_cmd_driv_ctr_write; /* 0x10 */ - uint16_t ap_to_bg_int_src; /* 0x14 */ - uint16_t bg_to_ap_int_src; /* 0x16 */ - uint32_t mxlog_filter; /* 0x18 */ - uint32_t firmware_control; /* 0x1C */ - uint8_t reserved1[0x20]; /* 0x20 */ - - /* AP RO - R4 RW - 64 octets */ - uint32_t mailbox_cmd_driv_ctr_read; /* 0x40 */ - uint32_t mailbox_cmd_ctr_driv_write; /* 0x44 */ - uint32_t mailbox_data_driv_ctr_read; /* 0x48 */ - uint32_t mailbox_data_ctr_driv_write; /* 0x4C */ - uint32_t firmware_features; /* 0x50 */ - uint16_t panic_deathbed_confession; /* 0x54 */ - uint8_t reserved2[0x2A]; /* 0x56 */ -}; - -struct ASMHCP_PROTOCOL { - /* header offset: 0x00000000 */ - volatile struct ASMHCP_HEADER header; - /* from controller */ - struct ASMHCP_TD_CONTROL /* offset: 0x00000080 */ - cmd_controller_driver_transfer_ring[ASMHCP_TRANSFER_RING_CMD_SIZE]; - struct ASMHCP_TD_CONTROL /* offset: 0x000008A0 */ - data_controller_driver_transfer_ring[ASMHCP_TRANSFER_RING_DATA_SIZE]; - - /* Padding used to ensure minimum 32 octets between sections */ - uint8_t reserved[0x20]; /* offset: 0x000010C0 */ - - /* from driver */ - struct ASMHCP_TD_CONTROL /* offset: 0x000010E0 */ - cmd_driver_controller_transfer_ring[ASMHCP_TRANSFER_RING_CMD_SIZE]; - struct ASMHCP_TD_CONTROL /* offset: 0x00001900 */ - data_driver_controller_transfer_ring[ASMHCP_TRANSFER_RING_DATA_SIZE]; -}; - -#define ASMHCP_PROTOCOL_MAGICVALUE \ - ((ASMHCP_TRANSFER_RING_DATA_SIZE | (ASMHCP_TRANSFER_RING_CMD_SIZE << 4) | \ - (offsetof(struct ASMHCP_PROTOCOL, cmd_driver_controller_transfer_ring) << 15)) ^ \ - sizeof(struct ASMHCP_PROTOCOL)) - -#endif /* __ASMHCP_H__ */ diff --git a/include/scsc/api/bhcs.h b/include/scsc/api/bhcs.h deleted file mode 100644 index 7101db580506..000000000000 --- a/include/scsc/api/bhcs.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/**************************************************************************** - * FILE - * bhcs.h - Bluetooth Host Configuration Structure - * - * DESCRIPTION - * This file specifies the layout of the Bluetooth Host Configuration - * Structure. The structure is written by the host and passed to the - * firmware as an argument to the service start callback function in - * the form of an offset that must be converted to a local address. - * - * ASSUMPTIONS - * The host and the firmware has the same endiannes. - * The ABI on the host and the firmware results in the same memory - * layout of the defined structure. - * - */ - -#ifndef BHCS_H__ -#define BHCS_H__ - -/* The version of the BHCS structure. Must be written to the version field - * by the host and confirmed to match the define by the firmware. Increment - * the version when changing the layout of the structure. This also serves - * as a rudimentary endianess check. */ -#define BHCS_VERSION 2 - -struct BHCS { - uint32_t version; /* BHCS_VERSION */ - uint32_t bsmhcp_protocol_offset; /* BSMHCP_PROTOCOL structure offset */ - uint32_t bsmhcp_protocol_length; /* BSMHCP_PROTOCOL structure length */ - uint32_t configuration_offset; /* Binary configuration data offset */ - uint32_t configuration_length; /* Binary configuration data length */ - uint32_t bluetooth_address_lap; /* Lower Address Part 00..23 */ - uint8_t bluetooth_address_uap; /* Upper Address Part 24..31 */ - uint16_t bluetooth_address_nap; /* Non-significant 32..47 */ -}; - -#endif /* BHCS_H__ */ diff --git a/include/scsc/api/bsmhcp.h b/include/scsc/api/bsmhcp.h deleted file mode 100755 index b1bbbfc5ceaf..000000000000 --- a/include/scsc/api/bsmhcp.h +++ /dev/null @@ -1,325 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -/**************************************************************************** - * FILE - * bsmhcp.h - Bluetooth Shared Memory Host Controller Protocol - * - * DESCRIPTION - * This file specifies the layout of the Bluetooth Shared Memory - * Host Controller Protocol as described in SC-505753-DD - */ - -#ifndef __BSMHCP_H__ -#define __BSMHCP_H__ - -#define BSMHCP_TRANSFER_RING_CMD_SIZE (8) -#define BSMHCP_TRANSFER_RING_EVT_SIZE (32) -#define BSMHCP_TRANSFER_RING_ACL_SIZE (32) -#define BSMHCP_TRANSFER_RING_AVDTP_SIZE (16) -#define BSMHCP_TRANSFER_RING_IQ_REPORT_SIZE (8) - -/* Of the buffers in BSMHCP_TRANSFER_RING_ACL_SIZE, reserve a number for ULP - * operation. */ -#define BSMHCP_TRANSFER_RING_ACL_ULP_RESERVED (4) -#define BSMHCP_TRANSFER_RING_SCO_SIZE (0) -#define BSMHCP_TRANSFER_RING_ACL_COUNT (36) -#define BSMHCP_TRANSFER_RING_TIMING_COUNT (64) - -#define BSMHCP_CMD_EVT_BUFFER_SIZE (258) -#define BSMHCP_ACL_BUFFER_SIZE (1024) -#define BSMHCP_IQ_REPORT_BUFFER_SIZE (164) - -#define BSMHCP_ACL_PACKET_SIZE (1021) -#define BSMHCP_ULP_PACKET_SIZE BSMHCP_ACL_PACKET_SIZE -#define BSMHCP_SCO_PACKET_SIZE (0) - -#define BSMHCP_DATA_BUFFER_CMD_SIZE \ - BSMHCP_TRANSFER_RING_CMD_SIZE -#define BSMHCP_DATA_BUFFER_EVT_SIZE \ - BSMHCP_TRANSFER_RING_EVT_SIZE -#define BSMHCP_DATA_BUFFER_TX_ACL_SIZE \ - (BSMHCP_TRANSFER_RING_ACL_SIZE - 2) -#define BSMHCP_DATA_BUFFER_RX_ACL_SIZE \ - BSMHCP_TRANSFER_RING_ACL_SIZE - -#define BSMHCP_EVENT_TYPE_NONE (0x00) -#define BSMHCP_EVENT_TYPE_CONNECTED (0x01) -#define BSMHCP_EVENT_TYPE_DISCONNECTED (0x02) - -#define BSMHCP_ACL_BC_FLAG_BCAST_NON (0x00) -#define BSMHCP_ACL_BC_FLAG_BCAST_ACTIVE (0x40) -#define BSMHCP_ACL_BC_FLAG_BCAST_ALL (0x80) -#define BSMHCP_ACL_BC_FLAG_BCAST_RSVD (0xC0) -#define BSMHCP_ACL_BC_FLAG_BCAST_MASK (0xC0) - -#define BSMHCP_ACL_PB_FLAG_START_NONFLUSH (0x00) -#define BSMHCP_ACL_PB_FLAG_CONT (0x10) -#define BSMHCP_ACL_PB_FLAG_START_FLUSH (0x20) -#define BSMHCP_ACL_PB_FLAG_RSVD_3 (0x30) -#define BSMHCP_ACL_PB_FLAG_MASK (0x30) - -#define BSMHCP_ACL_L2CAP_FLAG_NON (0x00) -#define BSMHCP_ACL_L2CAP_FLAG_END (0x01) -#define BSMHCP_ACL_L2CAP_FLAG_MASK (0x01) - -#define BSMHCP_SERVICE_BT_STATE_INACTIVE (0x00) -#define BSMHCP_SERVICE_BT_STATE_ACTIVE (0x01) - -#define BSMHCP_CONTROLLER_STATE_ACTIVE (0x00000001) - -#define BSMHCP_HCI_CONNECTION_HANDLE_LOOPBACK (0x4000) - -#define BSMHCP_ALIGNMENT (32) - -#define BSMHCP_FEATURE_LPA2DP (0x00000001) -#define BSMHCP_FEATURE_M4_INTERRUPTS (0x00000002) -#define BSMHCP_FEATURE_FW_INFORMATION (0x00000004) -#define BSMHCP_FEATURE_AVDTP_TRANSFER_RING (0x00000008) - -#define BSMHCP_CONTROL_START_PANIC (0x10DEAD01) -#define BSMHCP_CONTROL_STOP_PANIC (0x0201DEAD) -#define BSMHCP_CONTROL_CONNECTION_PANIC (0xDEAD2002) - -#define BSMHCP_FW_INFO_USER_DEFINED_COUNT (96) - -#define BSMHCP_TIMING_SOURCE_ITIME (0) -#define BSMHCP_TIMING_SOURCE_ITIME_L1 (1) -#define BSMHCP_TIMING_SOURCE_RADIO_TX (2) -#define BSMHCP_TIMING_SOURCE_RADIO_RX (3) -#define BSMHCP_TIMING_SOURCE_RADIO_LC (4) -#define BSMHCP_TIMING_SOURCE_COUNT (5) - -#define BSMHCP_INCREASE_INDEX(index, limit) \ - ((index) = ((index) + 1) % (limit)) - -#define BSMHCP_HAS_ROOM(write, read, limit) \ - ((((write) + 1) % (limit)) != (read)) - -struct BSMHCP_TD_CONTROL { - uint16_t length; - uint8_t data[BSMHCP_CMD_EVT_BUFFER_SIZE]; -}; - -struct BSMHCP_TD_HCI_EVT { - uint16_t length; - uint16_t hci_connection_handle; - uint16_t event_type; - uint8_t data[BSMHCP_CMD_EVT_BUFFER_SIZE]; -}; - -struct BSMHCP_TD_ACL_RX { - uint16_t hci_connection_handle; - uint16_t length; - uint8_t broadcast_flag; - uint8_t packet_boundary; - uint8_t disconnected; - uint8_t reserved; - uint8_t data[BSMHCP_ACL_BUFFER_SIZE]; -}; - -struct BSMHCP_TD_ACL_TX_DATA { - uint16_t length; - uint8_t buffer_index; - uint8_t flags; - uint16_t hci_connection_handle; - uint16_t l2cap_cid; -}; - -struct BSMHCP_TD_ACL_TX_FREE { - uint8_t buffer_index; - uint8_t reserved; - uint16_t hci_connection_handle; -}; - -struct BSMHCP_TD_AVDTP { - uint32_t flags; - uint16_t l2cap_cid; - uint16_t hci_connection_handle; - uint32_t reserved; -}; - -struct BSMHCP_ACL_TR_DRV_INDEX { - uint32_t read_free; - uint32_t write_data; -}; - -struct BSMHCP_ACL_TR_CTRL_INDEX { - uint32_t read_data; - uint32_t write_free; -}; - -struct BSMHCP_INDEX { - uint32_t read; - uint32_t write; -}; - -struct BSMHCP_TIMING_PACKET { - uint16_t source; - uint16_t sequence_number; - uint32_t interrupt_enter; - uint32_t critical_section_enter; - uint32_t time[4]; - uint32_t critical_section_leave; - uint32_t interrupt_leave; -}; - -struct BSMHCP_FW_INFO { - uint32_t r4_from_ap_interrupt_count; - uint32_t m4_from_ap_interrupt_count; - uint32_t r4_to_ap_interrupt_count; - uint32_t m4_to_ap_interrupt_count; - uint32_t bt_deep_sleep_time_total; - uint32_t bt_deep_sleep_wakeup_duration; - uint32_t sched_n_messages; - uint32_t user_defined_count; - uint32_t user_defined[BSMHCP_FW_INFO_USER_DEFINED_COUNT]; -}; - -struct BSMHCP_TD_IQ_REPORTING_EVT { - uint8_t subevent_code; - uint8_t packet_status; - uint16_t connection_handle; - uint16_t sync_handle; - uint8_t rx_phy; - uint8_t channel_index; - int16_t rssi; - uint8_t rssi_antenna_id; - uint8_t cte_type; - uint8_t slot_durations; - uint8_t sample_count; - uint16_t event_count; - uint8_t data[BSMHCP_IQ_REPORT_BUFFER_SIZE]; -}; - -struct BSMHCP_HEADER { - /* AP RW - M4/R4 RO - 64 octets */ - uint32_t magic_value; /* 0x00 */ - uint16_t ap_to_fg_m4_int_src; /* 0x04 */ - uint8_t service_request; /* 0x06 */ - uint8_t reserved1; /* 0x07 */ - uint32_t acl_buffer_size; /* 0x08 */ - uint32_t cmd_evt_buffer_size; /* 0x0C */ - uint32_t acl_tx_buffers; /* 0x10 */ - uint16_t ap_to_bg_int_src; /* 0x14 */ - uint16_t ap_to_fg_int_src; /* 0x16 */ - uint16_t bg_to_ap_int_src; /* 0x18 */ - uint16_t fg_to_ap_int_src; /* 0x1A */ - uint32_t mailbox_offset; /* 0x1C */ - uint32_t reserved1_u32; /* 0x20 */ - uint32_t mailbox_hci_cmd_write; /* 0x24 */ - uint32_t mailbox_hci_evt_read; /* 0x28 */ - uint32_t mailbox_acl_tx_write; /* 0x2C */ - uint32_t mailbox_acl_free_read; /* 0x30 */ - uint32_t mailbox_acl_rx_read; /* 0x34 */ - uint32_t abox_offset; /* 0x38 */ - uint32_t abox_length; /* 0x3C */ - - /* AP RO - R4 RW - M4 NA - 32 octets */ - uint16_t panic_deathbed_confession; /* 0x40 */ - uint16_t panic_diatribe_value; /* 0x42 */ - uint32_t mailbox_hci_cmd_read; /* 0x44 */ - uint32_t mailbox_hci_evt_write; /* 0x48 */ - uint32_t controller_flags; /* 0x4C */ - uint32_t firmware_features; /* 0x50 */ - uint16_t reserved_u16; /* 0x54 */ - uint8_t service_state; /* 0x56 */ - uint8_t reserved_u8; /* 0x57 */ - uint32_t reserved4_u32; /* 0x58 */ - uint32_t mailbox_avdtp_read; /* 0x5C */ - - /* AP RO - R4 NA - M4 RW - 32 octets */ - uint32_t mailbox_acl_tx_read; /* 0x60 */ - uint32_t mailbox_acl_free_write; /* 0x64 */ - uint32_t mailbox_acl_rx_write; /* 0x68 */ - uint32_t mailbox_timing_write; /* 0x6C */ - uint32_t mailbox_iq_report_write; /* 0x70 */ - uint8_t reserved4[0x0C]; /* 0x74 */ - - - /* AP RO - R4/M4 RW - 32 octets */ - uint32_t reserved6_u32; /* 0x80 */ - uint8_t reserved5[0x1C]; /* 0x84 */ - - /* AP RW - M4/R4 RO */ - uint32_t mailbox_timing_read; /* 0xA0 */ - uint32_t mailbox_avdtp_write; /* 0xA4 */ - uint32_t mailbox_iq_report_read; /* 0xA8 */ - uint32_t reserved9_u32; /* 0xAC */ - uint32_t reserved10_u32; /* 0xB0 */ - uint32_t reserved11_u32; /* 0xB4 */ - uint32_t reserved12_u32; /* 0xB8 */ - uint16_t info_ap_to_bg_int_src; /* 0xBC */ - uint16_t info_bg_to_ap_int_src; /* 0xBE */ - uint32_t mxlog_filter; /* 0xC0 */ - uint32_t firmware_control; /* 0xC4 */ - uint8_t reserved6[0x24]; /* 0xC8 */ - - /* Obsolete region - not used */ - uint32_t smm_debug_read; /* 0xEC */ - uint32_t smm_debug_write; /* 0xF0 */ - uint32_t smm_exception; /* 0xF4 */ - uint32_t avdtp_detect_stream_id; /* 0xF8 */ - uint32_t smm_int_ready; /* 0xFE */ -}; - -struct BSMHCP_PROTOCOL { - /* header offset: 0x00000000 */ - volatile struct BSMHCP_HEADER header; - - /* from AP */ - struct BSMHCP_TD_CONTROL /* offset: 0x00000100 */ - hci_cmd_transfer_ring[BSMHCP_TRANSFER_RING_CMD_SIZE]; - - /* AVDTP detection */ - struct BSMHCP_TD_AVDTP /* offset: 0x00000920 */ - avdtp_transfer_ring[BSMHCP_TRANSFER_RING_AVDTP_SIZE]; - - uint8_t /* offset: 0x000009E0 */ - to_air_reserved[0x1FC0]; - - struct BSMHCP_TD_ACL_TX_DATA /* offset: 0x000029A0 */ - acl_tx_data_transfer_ring[BSMHCP_TRANSFER_RING_ACL_SIZE]; - - uint8_t /* offset: 0x00002AA0 */ - acl_tx_buffer[BSMHCP_DATA_BUFFER_TX_ACL_SIZE] - [BSMHCP_ACL_BUFFER_SIZE]; - - /* Padding used to ensure minimum 32 octets between sections */ - uint8_t reserved[0x20]; /* offset: 0x0000A2A0 */ - - /* to AP */ - struct BSMHCP_TD_HCI_EVT /* offset: 0x0000A2C0 */ - hci_evt_transfer_ring[BSMHCP_TRANSFER_RING_EVT_SIZE]; - - struct BSMHCP_TIMING_PACKET /* offset: 0x0000C3C0 */ - timing_transfer_ring[BSMHCP_TRANSFER_RING_TIMING_COUNT]; - - struct BSMHCP_FW_INFO /* offset: 0x0000CCC0 */ - information; - - uint8_t /* offset: 0x0000CCC0 + sizoef(struct BSMHCP_FW_INFO) */ - from_air_reserved[0x11E0 - sizeof(struct BSMHCP_FW_INFO)]; - - struct BSMHCP_TD_IQ_REPORTING_EVT /* offset: 0x0000DEA0 */ - iq_reporting_transfer_ring[BSMHCP_TRANSFER_RING_IQ_REPORT_SIZE]; - - struct BSMHCP_TD_ACL_RX /* offset: 0x0000E440 */ - acl_rx_transfer_ring[BSMHCP_TRANSFER_RING_ACL_SIZE]; - - struct BSMHCP_TD_ACL_TX_FREE /* offset: 0x00016540 */ - acl_tx_free_transfer_ring[BSMHCP_TRANSFER_RING_ACL_SIZE]; -}; - -#define BSMHCP_TD_ACL_RX_CONTROL_SIZE \ - (sizeof(struct BSMHCP_TD_ACL_RX) - BSMHCP_ACL_BUFFER_SIZE) - -#define BSMHCP_PROTOCOL_MAGICVALUE \ - ((BSMHCP_ACL_BUFFER_SIZE | BSMHCP_CMD_EVT_BUFFER_SIZE | \ - (offsetof(struct BSMHCP_PROTOCOL, acl_tx_buffer) << 15)) ^ \ - sizeof(struct BSMHCP_PROTOCOL)) - -#endif /* __BSMHCP_H__ */ diff --git a/include/scsc/api/bt_audio.h b/include/scsc/api/bt_audio.h deleted file mode 100755 index 00a3bc67655d..000000000000 --- a/include/scsc/api/bt_audio.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef _BT_AUDIO_H -#define _BT_AUDIO_H - -/* Version number */ -#define SCSC_BT_AUDIO_ABOX_VERSION_MAJOR (0x01) -#define SCSC_BT_AUDIO_ABOX_VERSION_MINOR (0x01) - -/* The A-Box uses a ARM Cortex-A7 with a 64 bytes cache line whereas - * the WLBT uses a ARM Cortex-R4 with a 32 bytes cache line. The data - * needs to be aligned to the largest cache line - */ -#define SCSC_BT_AUDIO_ABOX_DCACHE_LINE_WIDTH (64) - -/* kernel page size used for memory alignment */ -#define SCSC_BT_AUDIO_PAGE_SIZE (PAGE_SIZE) - -/* Total size of the shared memory in one direction */ -#define SCSC_BT_AUDIO_ABOX_DATA_SIZE (128 * SCSC_BT_AUDIO_ABOX_DCACHE_LINE_WIDTH) - -/* Size of the buffer for each interface */ -#define SCSC_BT_AUDIO_ABOX_IF_0_SIZE (10 * SCSC_BT_AUDIO_ABOX_DCACHE_LINE_WIDTH) -#define SCSC_BT_AUDIO_ABOX_IF_1_SIZE (10 * SCSC_BT_AUDIO_ABOX_DCACHE_LINE_WIDTH) - -/* Feature mask */ -#define SCSC_BT_AUDIO_FEATURE_STREAMING_IF_0 (0x00000001) -#define SCSC_BT_AUDIO_FEATURE_STREAMING_IF_1 (0x00000002) -#define SCSC_BT_AUDIO_FEATURE_MESSAGING (0x00000004) -#define SCSC_BT_AUDIO_FEATURE_A2DP_OFFLOAD (0x00000008) - -struct scsc_bt_audio_abox { - /* AP RW - BT R4 RO - ABOX RO - 128 octets */ - - /* header */ - uint32_t magic_value; - uint16_t version_major; - uint16_t version_minor; - - /* align to cache line (32 bytes) */ - uint8_t reserved1[0x18]; - - /* streaming interface 0 */ - uint32_t abox_to_bt_streaming_if_0_size; - - /* offset in abox_to_bt_streaming_if_data */ - uint32_t abox_to_bt_streaming_if_0_offset; - - uint32_t bt_to_abox_streaming_if_0_size; - - /* offset in bt_to_abox_streaming_if_data */ - uint32_t bt_to_abox_streaming_if_0_offset; - - /* streaming interface 1 */ - uint32_t abox_to_bt_streaming_if_1_size; - - /* offset in abox_to_bt_streaming_if_data */ - uint32_t abox_to_bt_streaming_if_1_offset; - - uint32_t bt_to_abox_streaming_if_1_size; - - /* offset in bt_to_abox_streaming_if_data */ - uint32_t bt_to_abox_streaming_if_1_offset; - - /* reserved room for additional AP information (64 bytes) */ - uint8_t reserved2[0x40]; - - /* AP RO - BT R4 RO - ABOX RW - 64 octets */ - uint32_t abox_fw_features; - - /* BTWLAN audio and ABOX firmware may start at different time - * and a number of interrupts may be already triggered by ABOX - * firmware before BTWLAN audio can process them causing - * misalignment between the two systems (e.g. both accessing - * the same buffer at the same time). The fields below provide - * information about which half of the double buffer the ABOX - * firmware is processing using 0/1. - * filled by ABOX firmware at each interrupt (read/write) and - * initialised to 0 by BT driver. - */ - uint32_t bt_to_abox_streaming_if_0_current_index; - uint32_t abox_to_bt_streaming_if_0_current_index; - uint32_t bt_to_abox_streaming_if_1_current_index; - uint32_t abox_to_bt_streaming_if_1_current_index; - - /* align to cache line (64 bytes) */ - uint8_t reserved3[0x2C]; - - /* AP RO - BT R4 RW - ABOX RO - 64 octets */ - uint32_t bt_fw_features; - - /* sample rate (Hz) of the streaming interfaces */ - uint32_t streaming_if_0_sample_rate; - uint32_t streaming_if_1_sample_rate; - - uint8_t reserved4[0x34]; - - /* payload */ - - /* AP RO - BT R4 RO - ABOX RW - multiple of 64 octets */ - uint8_t abox_to_bt_streaming_if_data[SCSC_BT_AUDIO_ABOX_DATA_SIZE]; - - /* AP RO - BT R4 RW - ABOX RO - multiple of 64 octets */ - uint8_t bt_to_abox_streaming_if_data[SCSC_BT_AUDIO_ABOX_DATA_SIZE]; -}; - -/* Magic value */ -#define SCSC_BT_AUDIO_ABOX_MAGIC_VALUE \ - (((offsetof(struct scsc_bt_audio_abox, abox_to_bt_streaming_if_0_size) << 20) | \ - (offsetof(struct scsc_bt_audio_abox, bt_to_abox_streaming_if_0_current_index) << 10) | \ - offsetof(struct scsc_bt_audio_abox, abox_to_bt_streaming_if_data)) ^ \ - 0xBA12EF82) - -struct scsc_bt_audio { - struct device *dev; - struct scsc_bt_audio_abox *abox_virtual; - struct scsc_bt_audio_abox *abox_physical; - int (*dev_iommu_map)(struct device *, phys_addr_t, size_t); - void (*dev_iommu_unmap)(struct device *, size_t); -}; - -struct scsc_bt_audio_driver { - const char *name; - void (*probe)(struct scsc_bt_audio_driver *driver, struct scsc_bt_audio *bt_audio); - void (*remove)(struct scsc_bt_audio *bt_audio); -}; - -phys_addr_t scsc_bt_audio_get_paddr_buf(bool tx); -unsigned int scsc_bt_audio_get_rate(int id); -int scsc_bt_audio_register(struct device *dev, - int (*dev_iommu_map)(struct device *, phys_addr_t, size_t), - void (*dev_iommu_unmap)(struct device *, size_t)); -int scsc_bt_audio_unregister(struct device *dev); - -#endif /* _BT_AUDIO_H */ diff --git a/include/scsc/api/cme3_prim.h b/include/scsc/api/cme3_prim.h deleted file mode 100644 index 8a8674ab2113..000000000000 --- a/include/scsc/api/cme3_prim.h +++ /dev/null @@ -1,375 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2015 Samsung Electronics Co., Ltd - * Confidential information of Samsung Electronics Co., Ltd - * - * Refer to LICENSE.txt included with this source for details - * on the license terms. - * - * CME3_PRIM_H defines data structures and macros for coex signalling - * between BT Host and BT FW - * - *****************************************************************************/ -#ifndef CME3_PRIM_H__ -#define CME3_PRIM_H__ - -#if defined(XAP) -#include "types.h" -#else -#include -#include -#endif - -#define CME3_PRIM_ANY_SIZE 1 - -/******************************************************************************* - * - * NAME - * CME_Signal_Id - * - * DESCRIPTION - * - * VALUES - * profile_a2dp_start_ind - - * profile_a2dp_stop_ind - - * coex_stop_ind - - * coex_start_ind - - * - *******************************************************************************/ -typedef enum { - CME_SIGNAL_ID_PROFILE_A2DP_START_IND = 0, - CME_SIGNAL_ID_PROFILE_A2DP_STOP_IND = 1, - CME_SIGNAL_ID_COEX_STOP_IND = 2, - CME_SIGNAL_ID_COEX_START_IND = 3, -} CME_SIGNAL_ID; - -/******************************************************************************* - * - * NAME - * CME_CODEC_TYPE - * - * DESCRIPTION - * Codec types used for A2DP profile. - * - * VALUES - * CME_CODEC_TYPE_SBC - - * CME_CODEC_TYPE_APTX - - * CME_CODEC_TYPE_SSHD - - * - *******************************************************************************/ -typedef enum { - CME_CODEC_TYPE_SBC = 0, - CME_CODEC_TYPE_APTX = 1, - CME_CODEC_TYPE_SSHD = 2 -} CME_CODEC_TYPE; - - -/******************************************************************************* - * - * NAME - * CME_A2DP_ROLE - * - * DESCRIPTION - * A2DP Device role for A2DP profile. - * - * VALUES - * CME_A2DP_SOURCE - - * CME_A2DP_SINK - - * - *******************************************************************************/ -typedef enum { - CME_A2DP_SOURCE = 0, - CME_A2DP_SINK = 1 -} CME_A2DP_ROLE; - - -/******************************************************************************* - * - * NAME - * Cme_Header - * - * DESCRIPTION - * - * MEMBERS - * Signal_Id - - * Length - The length of the whole message in 16-bit words. - * - *******************************************************************************/ -typedef struct { - CME_SIGNAL_ID Signal_Id; - uint8_t Length; -} CME_HEADER; - -/* The following macros take CME_HEADER *cme_header_ptr or uint16_t *addr */ -#define CME_HEADER_SIGNAL_ID_WORD_OFFSET (0) - -#define CME_HEADER_SIGNAL_ID_GET(addr) \ - ((CME_SIGNAL_ID)((*(((volatile const uint16_t *)(addr))) & 0xff))) - -#define CME_HEADER_SIGNAL_ID_SET(addr, signal_id) \ - (*(((volatile uint16_t *)(addr))) = \ - (uint16_t)((*(((volatile uint16_t *)(addr))) & ~0xff) | (((signal_id)) & 0xff))) - -#define CME_HEADER_LENGTH_GET(addr) (((*(((volatile const uint16_t *)(addr))) & 0xff00) >> 8)) - -#define CME_HEADER_LENGTH_SET(addr, length) (*(((volatile uint16_t *)(addr))) = \ - (uint16_t)((*(((volatile uint16_t *)(addr))) & ~0xff00) | (((length) << 8) & 0xff00))) - -#define CME_HEADER_WORD_SIZE (1) - -/*lint -e(773) allow unparenthesized*/ -#define CME_HEADER_CREATE(Signal_Id, Length) \ - (uint16_t)(((Signal_Id)) & 0xff) | \ - (uint16_t)(((Length) << 8) & 0xff00) - -#define CME_HEADER_PACK(addr, Signal_Id, Length) \ - do { \ - *(((volatile uint16_t *)(addr))) = (uint16_t)((uint16_t)(((Signal_Id)) & 0xff) | \ - (uint16_t)(((Length) << 8) & 0xff00)); \ - } while (0) - -#define CME_HEADER_MARSHALL(addr, cme_header_ptr) \ - do { \ - *((addr)) = (uint16_t)((((cme_header_ptr)->Signal_Id)) & 0xff) | \ - (uint16_t)((((cme_header_ptr)->Length) << 8) & 0xff00); \ - } while (0) - -#define CME_HEADER_UNMARSHALL(addr, cme_header_ptr) \ - do { \ - (cme_header_ptr)->Signal_Id = CME_HEADER_SIGNAL_ID_GET(addr); \ - (cme_header_ptr)->Length = CME_HEADER_LENGTH_GET(addr); \ - } while (0) - - - - -/******************************************************************************* - * - * NAME - * CME_PROFILE_A2DP_START_IND - * - * DESCRIPTION - * Message from CME_BH to CME_BT to indicate that an A2DP profile has - * started a connection or that an existing connection has resumed with - * updated parameters. - * - * MEMBERS - * acl_handle - Identifies the ACL Link used for the profile - * connection. - * l2cap_connection_id - Identifies the remote L2CAP connection ID (as used on - * the air). - * bit_rate - Identifies the bit rate of the codec in kbps. - * codec_type - Identifies the codec type (CME_CODEC_TYPE enum). - * sdu_size - Identifies the maximum size of the A2DP SDU (MTU - * negotiated for the L2CAP link) in octets. - * period - Identifies the period in ms of codec data being - * available for transmission. - * role - Identifies the local device role, source or sink. - * spare - Spare. - * - *******************************************************************************/ -typedef struct { - CME_HEADER header; - uint16_t acl_handle; - uint16_t l2cap_connection_id; - uint16_t bit_rate; /* Only 12 bits used */ - CME_CODEC_TYPE codec_type; - uint16_t sdu_size; - uint8_t period; - CME_A2DP_ROLE role; -} CME_PROFILE_A2DP_START_IND; - -/* The following macros take - * CME_PROFILE_A2DP_START_IND *cme_profile_a2dp_start_ind_ptr or uint16_t *addr */ -#define CME_PROFILE_A2DP_START_IND_ACL_HANDLE_WORD_OFFSET (1) - -#define CME_PROFILE_A2DP_START_IND_ACL_HANDLE_GET(addr) (*((addr) + 1)) - -#define CME_PROFILE_A2DP_START_IND_ACL_HANDLE_SET(addr, acl_handle) \ - (*((addr) + 1) = (uint16_t)(acl_handle)) - -#define CME_PROFILE_A2DP_START_IND_L2CAP_CONNECTION_ID_WORD_OFFSET (2) - -#define CME_PROFILE_A2DP_START_IND_L2CAP_CONNECTION_ID_GET(addr) (*((addr) + 2)) - -#define CME_PROFILE_A2DP_START_IND_L2CAP_CONNECTION_ID_SET(addr, l2cap_connection_id) \ - (*((addr) + 2) = (uint16_t)(l2cap_connection_id)) -#define CME_PROFILE_A2DP_START_IND_BIT_RATE_WORD_OFFSET (3) - -#define CME_PROFILE_A2DP_START_IND_BIT_RATE_GET(addr) (((*((addr) + 3) & 0xfff))) - -#define CME_PROFILE_A2DP_START_IND_BIT_RATE_SET(addr, bit_rate) (*((addr) + 3) = \ - (uint16_t)((*((addr) + 3) & ~0xfff) | (((bit_rate)) & 0xfff))) - -#define CME_PROFILE_A2DP_START_IND_CODEC_TYPE_GET(addr) \ - ((CME_CODEC_TYPE)((*((addr) + 3) & 0x7000) >> 12)) - -#define CME_PROFILE_A2DP_START_IND_CODEC_TYPE_SET(addr, codec_type) \ - (*((addr) + 3) = \ - (uint16_t)((*((addr) + 3) & ~0x7000) | (((codec_type) << 12) & 0x7000))) - -#define CME_PROFILE_A2DP_START_IND_SDU_SIZE_WORD_OFFSET (4) - -#define CME_PROFILE_A2DP_START_IND_SDU_SIZE_GET(addr) (*((addr) + 4)) - -#define CME_PROFILE_A2DP_START_IND_SDU_SIZE_SET(addr, sdu_size) (*((addr) + 4) = \ - (uint16_t)(sdu_size)) - -#define CME_PROFILE_A2DP_START_IND_PERIOD_WORD_OFFSET (5) - -#define CME_PROFILE_A2DP_START_IND_PERIOD_GET(addr) (((*((addr) + 5) & 0xff))) - -#define CME_PROFILE_A2DP_START_IND_PERIOD_SET(addr, period) (*((addr) + 5) = \ - (uint16_t)((*((addr) + 5) & ~0xff) | (((period)) & 0xff))) - -#define CME_PROFILE_A2DP_START_IND_ROLE_GET(addr) \ - ((CME_A2DP_ROLE)((*((addr) + 5) & 0x100) >> 8)) - -#define CME_PROFILE_A2DP_START_IND_ROLE_SET(addr, role) (*((addr) + 5) = \ - (uint16_t)((*((addr) + 5) & ~0x100) | (((role) << 8) & 0x100))) - -#define CME_PROFILE_A2DP_START_IND_WORD_SIZE (6) - -#define CME_PROFILE_A2DP_START_IND_PACK(addr, acl_handle, l2cap_connection_id, \ - bit_rate, codec_type, sdu_size, period, role, sampling_freq) \ - do { \ - *((addr) + 1) = (uint16_t)((uint16_t)(acl_handle)); \ - *((addr) + 2) = (uint16_t)((uint16_t)(l2cap_connection_id)); \ - *((addr) + 3) = (uint16_t)((uint16_t)(((bit_rate)) & 0xfff) | \ - (uint16_t)(((codec_type) << 12) & 0x7000); \ - *((addr) + 4) = (uint16_t)((uint16_t)(sdu_size)); \ - *((addr) + 5) = (uint16_t)((uint16_t)(((period)) & 0xff) | \ - (uint16_t)(((role) << 8) & 0x100); \ - } while (0) - -#define CME_PROFILE_A2DP_START_IND_MARSHALL(addr, cme_profile_a2dp_start_ind_ptr) \ - do { \ - CME_HEADER_MARSHALL((addr), &((cme_profile_a2dp_start_ind_ptr)->header)); \ - *((addr) + 1) = (uint16_t)((cme_profile_a2dp_start_ind_ptr)->acl_handle); \ - *((addr) + 2) = (uint16_t)((cme_profile_a2dp_start_ind_ptr)->l2cap_connection_id); \ - *((addr) + 3) = (uint16_t)((((cme_profile_a2dp_start_ind_ptr)->bit_rate)) & 0xfff) | \ - (uint16_t)((((cme_profile_a2dp_start_ind_ptr)->codec_type) << 12) & 0x7000); \ - *((addr) + 4) = (uint16_t)((cme_profile_a2dp_start_ind_ptr)->sdu_size); \ - *((addr) + 5) = (uint16_t)((((cme_profile_a2dp_start_ind_ptr)->period)) & 0xff) | \ - (uint16_t)((((cme_profile_a2dp_start_ind_ptr)->role) << 8) & 0x100); \ - } while (0) - -#define CME_PROFILE_A2DP_START_IND_UNMARSHALL(addr, cme_profile_a2dp_start_ind_ptr) \ - do { \ - CME_HEADER_UNMARSHALL((addr), &((cme_profile_a2dp_start_ind_ptr)->header)); \ - (cme_profile_a2dp_start_ind_ptr)->acl_handle = CME_PROFILE_A2DP_START_IND_ACL_HANDLE_GET(addr); \ - (cme_profile_a2dp_start_ind_ptr)->l2cap_connection_id = CME_PROFILE_A2DP_START_IND_L2CAP_CONNECTION_ID_GET(addr); \ - (cme_profile_a2dp_start_ind_ptr)->bit_rate = CME_PROFILE_A2DP_START_IND_BIT_RATE_GET(addr); \ - (cme_profile_a2dp_start_ind_ptr)->codec_type = CME_PROFILE_A2DP_START_IND_CODEC_TYPE_GET(addr); \ - (cme_profile_a2dp_start_ind_ptr)->sdu_size = CME_PROFILE_A2DP_START_IND_SDU_SIZE_GET(addr); \ - (cme_profile_a2dp_start_ind_ptr)->period = CME_PROFILE_A2DP_START_IND_PERIOD_GET(addr); \ - (cme_profile_a2dp_start_ind_ptr)->role = CME_PROFILE_A2DP_START_IND_ROLE_GET(addr); \ - } while (0) - - -/******************************************************************************* - * - * NAME - * CME_PROFILE_A2DP_STOP_IND - * - * DESCRIPTION - * Message from CME_BH to CME_BT to indicate that an A2DP profile has - * stopped or paused. - * - * MEMBERS - * acl_handle - Identifies the ACL Link used for the profile - * connection. - * l2cap_connection_id - Identifies the remote L2CAP connection ID (as used on - * the air). - * - *******************************************************************************/ -typedef struct { - CME_HEADER header; - uint16_t acl_handle; - uint16_t l2cap_connection_id; -} CME_PROFILE_A2DP_STOP_IND; - -/* The following macros take - * CME_PROFILE_A2DP_STOP_IND *cme_profile_a2dp_stop_ind_ptr or uint16_t *addr */ -#define CME_PROFILE_A2DP_STOP_IND_ACL_HANDLE_WORD_OFFSET (1) - -#define CME_PROFILE_A2DP_STOP_IND_ACL_HANDLE_GET(addr) (*((addr) + 1)) - -#define CME_PROFILE_A2DP_STOP_IND_ACL_HANDLE_SET(addr, acl_handle) \ - (*((addr) + 1) = (uint16_t)(acl_handle)) - -#define CME_PROFILE_A2DP_STOP_IND_L2CAP_CONNECTION_ID_WORD_OFFSET (2) - -#define CME_PROFILE_A2DP_STOP_IND_L2CAP_CONNECTION_ID_GET(addr) (*((addr) + 2)) - -#define CME_PROFILE_A2DP_STOP_IND_L2CAP_CONNECTION_ID_SET(addr, l2cap_connection_id) \ - (*((addr) + 2) = (uint16_t)(l2cap_connection_id)) - -#define CME_PROFILE_A2DP_STOP_IND_WORD_SIZE (3) - -#define CME_PROFILE_A2DP_STOP_IND_PACK(addr, acl_handle, l2cap_connection_id) \ - do { \ - *((addr) + 1) = (uint16_t)((uint16_t)(acl_handle)); \ - *((addr) + 2) = (uint16_t)((uint16_t)(l2cap_connection_id)); \ - } while (0) - -#define CME_PROFILE_A2DP_STOP_IND_MARSHALL(addr, cme_profile_a2dp_stop_ind_ptr) \ - do { \ - CME_HEADER_MARSHALL((addr), &((cme_profile_a2dp_stop_ind_ptr)->header)); \ - *((addr) + 1) = (uint16_t)((cme_profile_a2dp_stop_ind_ptr)->acl_handle); \ - *((addr) + 2) = (uint16_t)((cme_profile_a2dp_stop_ind_ptr)->l2cap_connection_id); \ - } while (0) - -#define CME_PROFILE_A2DP_STOP_IND_UNMARSHALL(addr, cme_profile_a2dp_stop_ind_ptr) \ - do { \ - CME_HEADER_UNMARSHALL((addr), &((cme_profile_a2dp_stop_ind_ptr)->header)); \ - (cme_profile_a2dp_stop_ind_ptr)->acl_handle = CME_PROFILE_A2DP_STOP_IND_ACL_HANDLE_GET(addr); \ - (cme_profile_a2dp_stop_ind_ptr)->l2cap_connection_id = CME_PROFILE_A2DP_STOP_IND_L2CAP_CONNECTION_ID_GET(addr); \ - } while (0) - - - -/******************************************************************************* - * - * NAME - * CME_COEX_STOP_IND - * - * DESCRIPTION - * Message from CME_BT to CME_BH to indicate that the coex service is - * stopping. - * - * MEMBERS - * - *******************************************************************************/ -typedef struct { - CME_HEADER header; -} CME_COEX_STOP_IND; - -/* The following macros take - * CME_COEX_STOP_IND *cme_coex_stop_ind_ptr or uint16_t *addr */ -#define CME_COEX_STOP_IND_WORD_SIZE (1) - - -/******************************************************************************* - * - * NAME - * CME_COEX_START_IND - * - * DESCRIPTION - * Message from CME_BT to CME_BH to indicate that the coex service is - * starting. - * - * MEMBERS - * - *******************************************************************************/ -typedef struct { - CME_HEADER header; -} CME_COEX_START_IND; - -/* The following macros take - * CME_COEX_START_IND *cme_coex_start_ind_ptr or uint16_t *addr */ -#define CME_COEX_START_IND_WORD_SIZE (1) - - - -#endif /* CME3_PRIM_H__ */ diff --git a/include/scsc/kic/slsi_kic.h b/include/scsc/kic/slsi_kic.h deleted file mode 100755 index 8769268cd7fe..000000000000 --- a/include/scsc/kic/slsi_kic.h +++ /dev/null @@ -1,21 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_H -#define __SLSI_KIC_H - -#include - -int slsi_kic_system_event_ind(enum slsi_kic_system_event_category event_cat, - enum slsi_kic_system_events event, gfp_t flags); -int slsi_kic_service_information_ind(enum slsi_kic_technology_type tech, - struct slsi_kic_service_info *info); - -int slsi_kic_firmware_event_ind(uint16_t firmware_event_type, uint32_t tech_type, - uint32_t contain_type, - struct slsi_kic_firmware_event_ccp_host *event); - -#endif /* #ifndef __SLSI_KIC_H */ diff --git a/include/scsc/kic/slsi_kic_ant.h b/include/scsc/kic/slsi_kic_ant.h deleted file mode 100755 index 134890c21247..000000000000 --- a/include/scsc/kic/slsi_kic_ant.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_ANT_H -#define __SLSI_KIC_ANT_H - -#include - -/** - * struct slsi_kic_ant_ops - backend description for ANT service driver ops. - * - * This struct is registered by the ANT service driver during initilisation - * in order provide ANT specific services, which can be used by KIC. - * - * All callbacks except where otherwise noted should return 0 on success or a - * negative error code. - * - * @trigger_recovery: Trigger a ANT firmware subsystem recovery. The variable - * @type specifies the recovery type. - */ -struct slsi_kic_ant_ops { - int (*trigger_recovery)(void *priv, enum slsi_kic_test_recovery_type type); -}; - -#ifdef CONFIG_SAMSUNG_KIC - -/** - * slsi_kic_ant_ops_register - register ant_ops with KIC - * - * @priv: Private pointer, which will be included in all calls from KIC. - * @ant_ops: The ant_ops to register. - * - * Returns 0 on success or a negative error code. - */ -int slsi_kic_ant_ops_register(void *priv, struct slsi_kic_ant_ops *ant_ops); - -/** - * slsi_kic_ant_ops_unregister - unregister ant_ops with KIC - * - * @ant_ops: The ant_ops to unregister. - * - * After this call, no more requests can be made, but the call may sleep to wait - * for an outstanding request that is being handled. - */ -void slsi_kic_ant_ops_unregister(struct slsi_kic_ant_ops *ant_ops); - -#else - -#ifndef UNUSED -#define UNUSED(x) ((void)(x)) -#endif - -#define slsi_kic_ant_ops_register(a, b) \ - do { \ - UNUSED(a); \ - UNUSED(b); \ - } while (0) - -#define slsi_kic_ant_ops_unregister(a) UNUSED(a) -#endif /* CONFIG_SAMSUNG_KIC */ - -#endif /* #ifndef __SLSI_KIC_ANT_H */ diff --git a/include/scsc/kic/slsi_kic_bt.h b/include/scsc/kic/slsi_kic_bt.h deleted file mode 100755 index c779f01827d0..000000000000 --- a/include/scsc/kic/slsi_kic_bt.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_BT_H -#define __SLSI_KIC_BT_H - -#include - -/** - * struct slsi_kic_bt_ops - backend description for BT service driver ops. - * - * This struct is registered by the BT service driver during initilisation - * in order provide BT specific services, which can be used by KIC. - * - * All callbacks except where otherwise noted should return 0 on success or a - * negative error code. - * - * @trigger_recovery: Trigger a BT firmware subsystem recovery. The variable - * @type specifies the recovery type. - */ -struct slsi_kic_bt_ops { - int (*trigger_recovery)(void *priv, enum slsi_kic_test_recovery_type type); -}; - -#ifdef CONFIG_SAMSUNG_KIC - -/** - * slsi_kic_bt_ops_register - register bt_ops with KIC - * - * @priv: Private pointer, which will be included in all calls from KIC. - * @bt_ops: The bt_ops to register. - * - * Returns 0 on success or a negative error code. - */ -int slsi_kic_bt_ops_register(void *priv, struct slsi_kic_bt_ops *bt_ops); - -/** - * slsi_kic_bt_ops_unregister - unregister bt_ops with KIC - * - * @bt_ops: The bt_ops to unregister. - * - * After this call, no more requests can be made, but the call may sleep to wait - * for an outstanding request that is being handled. - */ -void slsi_kic_bt_ops_unregister(struct slsi_kic_bt_ops *bt_ops); - -#else - -#define slsi_kic_bt_ops_register(a, b) \ - do { \ - (void)(a); \ - (void)(b); \ - } while (0) - -#define slsi_kic_bt_ops_unregister(a) \ - do { \ - (void)(a); \ - } while (0) - -#endif /* CONFIG_SAMSUNG_KIC */ - -#endif /* #ifndef __SLSI_KIC_BT_H */ diff --git a/include/scsc/kic/slsi_kic_cm.h b/include/scsc/kic/slsi_kic_cm.h deleted file mode 100755 index de75c8e0aa1c..000000000000 --- a/include/scsc/kic/slsi_kic_cm.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_CM_H -#define __SLSI_KIC_CM_H - -#include - -/** - * struct slsi_kic_cm_ops - backend description for Chip Manager (CM) driver ops - * - * This struct is registered by the Chip Manager driver during initilisation - * in order provide CM specific services, which can be used by KIC. - * - * All callbacks except where otherwise noted should return 0 on success or a - * negative error code. - * - * @trigger_recovery: Trigger a firmware crash, which requires a full chip - * recovery. - * @type specifies the recovery type. - */ -struct slsi_kic_cm_ops { - int (*trigger_recovery)(void *priv, enum slsi_kic_test_recovery_type type); -}; - - -/** - * slsi_kic_cm_ops_register - register cm_ops with KIC - * - * @priv: Private pointer, which will be included in all calls from KIC. - * @wifi_ops: The wifi_ops to register. - * - * Returns 0 on success or a negative error code. - */ -int slsi_kic_cm_ops_register(void *priv, struct slsi_kic_cm_ops *cm_ops); - -/** - * slsi_kic_cm_ops_unregister - unregister cm_ops with KIC - * - * @cm_ops: The cm_ops to unregister. - * - * After this call, no more requests can be made, but the call may sleep to wait - * for an outstanding request that is being handled. - */ -void slsi_kic_cm_ops_unregister(struct slsi_kic_cm_ops *cm_ops); - -#endif /* #ifndef __SLSI_KIC_CM_H */ diff --git a/include/scsc/kic/slsi_kic_lib.h b/include/scsc/kic/slsi_kic_lib.h deleted file mode 100644 index 1543c8956dbb..000000000000 --- a/include/scsc/kic/slsi_kic_lib.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_LIB_H -#define __SLSI_KIC_LIB_H - -#ifdef CONFIG_SLSI_KIC_API_ENABLED -#include -#endif - -#include - -/** - * Library functions for sending information to kernel KIC, which will process - * the event and take appropriate action, i.e. forward to relevant user - * processes etc. - */ -#ifdef CONFIG_SLSI_KIC_API_ENABLED - -static inline void slsi_kic_system_event(enum slsi_kic_system_event_category event_cat, - enum slsi_kic_system_events event, gfp_t flags) -{ - (void)slsi_kic_system_event_ind(event_cat, event, flags); -} - - -static inline void slsi_kic_service_information(enum slsi_kic_technology_type tech, - struct slsi_kic_service_info *info) -{ - (void)slsi_kic_service_information_ind(tech, info); -} - -static inline void slsi_kic_firmware_event(uint16_t firmware_event_type, - enum slsi_kic_technology_type tech_type, - uint32_t contain_type, - struct slsi_kic_firmware_event_ccp_host *event) -{ - (void)slsi_kic_firmware_event_ind(firmware_event_type, tech_type, - contain_type, event); -} - -#else - -#define slsi_kic_system_event(a, b, c) \ - do { \ - (void)(a); \ - (void)(b); \ - (void)(c); \ - } while (0) - -#define slsi_kic_service_information(a, b) \ - do { \ - (void)(a); \ - (void)(b); \ - } while (0) - -#define slsi_kic_firmware_event(a, b, c, d) \ - do { \ - (void)(a); \ - (void)(b); \ - (void)(c); \ - (void)(d); \ - } while (0) - -#endif - -#endif /* #ifndef __SLSI_KIC_LIB_H */ diff --git a/include/scsc/kic/slsi_kic_prim.h b/include/scsc/kic/slsi_kic_prim.h deleted file mode 100755 index cdee9c0f57ad..000000000000 --- a/include/scsc/kic/slsi_kic_prim.h +++ /dev/null @@ -1,426 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_PRIM_H -#define __SLSI_KIC_PRIM_H - -#ifdef __KERNEL__ -#include -#else -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -#define SLSI_KIC_INTERFACE_VERSION_MAJOR 1 -#define SLSI_KIC_INTERFACE_VERSION_MINOR 0 - -/** - * Common - */ -enum slsi_kic_technology_type { - slsi_kic_technology_type_curator, - slsi_kic_technology_type_bt, - slsi_kic_technology_type_wifi, - slsi_kic_technology_type_audio, - slsi_kic_technology_type_gnss, - slsi_kic_technology_type_nfc, - slsi_kic_technology_type_janitor, - slsi_kic_technology_type_common, - slsi_kic_technology_type_ant, - - /* keep last */ - slsi_kic_technology_type__after_last, - slsi_kic_technology_type_max_category = slsi_kic_technology_type__after_last - 1 -}; - -static const char *const slsi_kic_technology_type_text[slsi_kic_technology_type_max_category + 1] = { - "curator", - "bt", - "wifi", - "audio", - "gnss", - "nfc", - "janitor", - "ant" -}; - -/** - * System events - */ -enum slsi_kic_system_event_category { - slsi_kic_system_event_category_initialisation, - slsi_kic_system_event_category_deinitialisation, - slsi_kic_system_event_category_error, - slsi_kic_system_event_category_recovery, - - /* keep last */ - slsi_kic_system_category__after_last, - slsi_kic_system_category_max_category = slsi_kic_system_category__after_last - 1 -}; - -static const char *const slsi_kic_system_category_text[slsi_kic_system_category_max_category + 1] = { - "Initialisation", - "Deinitialisation", - "Error", - "Recovery" -}; - -enum slsi_kic_system_events { - slsi_kic_system_events_wifi_on, - slsi_kic_system_events_wifi_off, - slsi_kic_system_events_wifi_suspend, - slsi_kic_system_events_wifi_resume, - slsi_kic_system_events_wifi_service_driver_attached, - slsi_kic_system_events_wifi_service_driver_detached, - slsi_kic_system_events_wifi_firmware_patch_downloaded, - slsi_kic_system_events_wifi_service_driver_started, - slsi_kic_system_events_wifi_service_driver_stopped, - slsi_kic_system_events_bt_on, - slsi_kic_system_events_bt_off, - slsi_kic_system_events_bt_service_driver_attached, - slsi_kic_system_events_bt_service_driver_detached, - slsi_kic_system_events_bt_firmware_patch_downloaded, - slsi_kic_system_events_curator_firmware_patch_downloaded, - slsi_kic_system_events_sdio_powered, - slsi_kic_system_events_sdio_inserted, - slsi_kic_system_events_sdio_removed, - slsi_kic_system_events_sdio_powered_off, - slsi_kic_system_events_sdio_error, - slsi_kic_system_events_uart_powered, - slsi_kic_system_events_uart_powered_off, - slsi_kic_system_events_uart_error, - slsi_kic_system_events_coredump_in_progress, - slsi_kic_system_events_coredump_done, - slsi_kic_system_events_subsystem_crashed, - slsi_kic_system_events_subsystem_recovered, - slsi_kic_system_events_host_ready_ind, - slsi_kic_system_events_ant_on, - slsi_kic_system_events_ant_off, - - /* keep last */ - slsi_kic_system_events__after_last, - slsi_kic_system_events_max_event = slsi_kic_system_events__after_last - 1 -}; - -static const char *const slsi_kic_system_event_text[slsi_kic_system_events_max_event + 1] = { - "Wi-Fi on", - "Wi-Fi off", - "Wi-Fi suspend", - "Wi-Fi resume", - "Wi-Fi service driver attached", - "Wi-Fi service driver detached", - "Wi-Fi firmware patch downloaded", - "Wi-Fi service driver started", - "Wi-Fi service driver stopped", - "BT on", - "BT off", - "BT service driver attached", - "BT service driver detached", - "BT firmware patch downloaded", - "Curator firmware patch downloaded", - "SDIO powered", - "SDIO inserted", - "SDIO removed", - "SDIO powered off", - "SDIO error", - "UART powered", - "UART powered off", - "UART error", - "Coredump in progress", - "Coredump done", - "Subsystem has crashed", - "Subsystem has been recovered", - "CCP Host ready Ind sent", - "ANT on", - "ANT off" -}; - -/** - * Time stamp - */ -struct slsi_kic_timestamp { - uint64_t tv_sec; /* seconds */ - uint64_t tv_nsec; /* nanoseconds */ -}; - -/* Policy */ -enum slsi_kic_attr_timestamp_attributes { - __SLSI_KIC_ATTR_TIMESTAMP_INVALID, - SLSI_KIC_ATTR_TIMESTAMP_TV_SEC, - SLSI_KIC_ATTR_TIMESTAMP_TV_NSEC, - - /* keep last */ - __SLSI_KIC_ATTR_TIMESTAMP_AFTER_LAST, - SLSI_KIC_ATTR_TIMESTAMP_MAX = __SLSI_KIC_ATTR_TIMESTAMP_AFTER_LAST - 1 -}; - - -/** - * Firmware event - */ -enum slsi_kic_firmware_event_type { - slsi_kic_firmware_event_type_panic, - slsi_kic_firmware_event_type_fault, - - /* keep last */ - slsi_kic_firmware_events__after_last, - slsi_kic_firmware_events_max_event = slsi_kic_firmware_events__after_last - 1 -}; - -static const char *const slsi_kic_firmware_event_type_text[slsi_kic_firmware_events_max_event + 1] = { - "Firmware panic", - "Firmware fault" -}; - -enum slsi_kic_firmware_container_type { - slsi_kic_firmware_container_type_ccp_host, -}; - - -/* - * Firmware event: CCP host container - */ -#define SLSI_KIC_FIRMWARE_EVENT_CCP_HOST_ARG_LENGTH 16 -struct slsi_kic_firmware_event_ccp_host { - uint32_t id; - uint32_t level; - char *level_string; - uint32_t timestamp; - uint32_t cpu; - uint32_t occurences; - uint32_t arg_length; - uint8_t *arg; -}; - -/** - * Trigger recovery - */ -enum slsi_kic_test_recovery_type { - slsi_kic_test_recovery_type_subsystem_panic, - slsi_kic_test_recovery_type_emulate_firmware_no_response, - slsi_kic_test_recovery_type_watch_dog, - slsi_kic_test_recovery_type_chip_crash, - slsi_kic_test_recovery_type_service_start_panic, - slsi_kic_test_recovery_type_service_stop_panic, -}; - -enum slsi_kic_test_recovery_status { - slsi_kic_test_recovery_status_ok, - slsi_kic_test_recovery_status_error_invald_param, - slsi_kic_test_recovery_status_error_send_msg, -}; - - -/* Policy */ -enum slsi_kic_attr_firmware_event_ccp_host_attributes { - __SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_INVALID, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_ID, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_LEVEL, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_LEVEL_STRING, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_TIMESTAMP, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_CPU, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_OCCURENCES, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_ARG, - - /* keep last */ - __SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_AFTER_LAST, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_MAX = __SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_AFTER_LAST - 1 -}; - - -/** - * System information - */ -struct slsi_kic_service_info { - char ver_str[128]; - uint16_t fw_api_major; - uint16_t fw_api_minor; - uint16_t release_product; - uint16_t host_release_iteration; - uint16_t host_release_candidate; -}; - -/* Policy */ -enum slsi_kic_attr_service_info_attributes { - __SLSI_KIC_ATTR_SERVICE_INFO_INVALID, - SLSI_KIC_ATTR_SERVICE_INFO_VER_STR, - SLSI_KIC_ATTR_SERVICE_INFO_FW_API_MAJOR, - SLSI_KIC_ATTR_SERVICE_INFO_FW_API_MINOR, - SLSI_KIC_ATTR_SERVICE_INFO_RELEASE_PRODUCT, - SLSI_KIC_ATTR_SERVICE_INFO_HOST_RELEASE_ITERATION, - SLSI_KIC_ATTR_SERVICE_INFO_HOST_RELEASE_CANDIDATE, - - /* keep last */ - __SLSI_KIC_ATTR_SERVICE_INFO_AFTER_LAST, - SLSI_KIC_ATTR_SERVICE_INFO_MAX = __SLSI_KIC_ATTR_SERVICE_INFO_AFTER_LAST - 1 -}; - - - -/** - * enum slsi_kic_commands - supported Samsung KIC commands - * - * @SLSI_KIC_CMD_UNSPEC: unspecified command to catch errors - * @SLSI_KIC_CMD_KIC_INTERFACE_VERSION_NUMBER_REQ: Requests the KIC interface - * version numbers to be send back. - * @SLSI_KIC_CMD_SYSTEM_EVENT_IND: Indicate a system event to user space. - * @SLSI_KIC_CMD_SERVICE_INFORMATION_REQ: Requests information for all - * already enabled subsystems. - * @SLSI_KIC_CMD_SERVICE_INFORMATION_IND: Indicate that a new subsystem has - * been started and the information for this subsystem. - * @SLSI_KIC_CMD_TEST_TRIGGER_RECOVERY_REQ: Triggers a recovery (crash) for a - * subsystem specified in the primitive. - * @SLSI_KIC_CMD_FIRMWARE_EVENT_IND: Indicates a firmware event to user space. - * @SLSI_KIC_CMD_ECHO_REQ: Request an echo (test primitive, which will be - * removed later). - * - * @SLSI_KIC_CMD_MAX: highest used command number - * @__SLSI_KIC_CMD_AFTER_LAST: internal use - */ -enum slsi_kic_commands { -/* Do not change the order or add anything between, this is ABI! */ - SLSI_KIC_CMD_UNSPEC, - - SLSI_KIC_CMD_KIC_INTERFACE_VERSION_NUMBER_REQ, - SLSI_KIC_CMD_SYSTEM_EVENT_IND, - SLSI_KIC_CMD_SERVICE_INFORMATION_REQ, - SLSI_KIC_CMD_SERVICE_INFORMATION_IND, - SLSI_KIC_CMD_TEST_TRIGGER_RECOVERY_REQ, - SLSI_KIC_CMD_FIRMWARE_EVENT_IND, - SLSI_KIC_CMD_ECHO_REQ, - - /* add new commands above here */ - - /* used to define SLSI_KIC_CMD_MAX below */ - __SLSI_KIC_CMD_AFTER_LAST, - SLSI_KIC_CMD_MAX = __SLSI_KIC_CMD_AFTER_LAST - 1 -}; - - -/** - * enum slsi_kic_attrs - Samsung KIC netlink attributes - * - * @SLSI_KIC_ATTR_UNSPEC: unspecified attribute to catch errors - * @SLSI_KIC_ATTR_KIC_VERSION_MAJOR: KIC version number - increments when the - * interface is updated with backward incompatible changes. - * @SLSI_KIC_ATTR_KIC_VERSION_MINOR: KIC version number - increments when the - * interface is updated with backward compatible changes. - * @SLSI_KIC_ATTR_TECHNOLOGY_TYPE: Technology type - * @SLSI_KIC_ATTR_SYSTEM_EVENT_CATEGORY: System event category - * @SLSI_KIC_ATTR_SYSTEM_EVENT: System event - * @SLSI_KIC_ATTR_SERVICE_INFO: Pass service info to user space. - * @SLSI_KIC_ATTR_NUMBER_OF_ENCODED_SERVICES: The attribute is used to determine - * the number of encoded services in the payload - * @SLSI_KIC_ATTR_TEST_RECOVERY_TYPE: Specifies the recovery type. - * @SLSI_KIC_ATTR_TIMESTAMP: A timestamp - ideally nano second resolution and - * precision, but it's platform dependent. - * @SLSI_KIC_ATTR_FIRMWARE_EVENT_TYPE: A firmware even type - panic or fault - * @SLSI_KIC_ATTR_FIRMWARE_CONTAINER_TYPE: Indicates container type carried in - * payload. - * @SLSI_KIC_ATTR_FIRMWARE_EVENT_CONTAINER_CCP_HOST: The firmware event data. - * @SLSI_KIC_ATTR_TRIGGER_RECOVERY_STATUS: Indicates if the recovery has been - * successfully triggered. The recovery signalling will happen afterwards as - * normal system events. - * @SLSI_KIC_ATTR_ECHO: An echo test primitive, which will be removed later. - * - * @SLSI_KIC_ATTR_MAX: highest attribute number currently defined - * @__SLSI_KIC_ATTR_AFTER_LAST: internal use - */ -enum slsi_kic_attrs { -/* Do not change the order or add anything between, this is ABI! */ - SLSI_KIC_ATTR_UNSPEC, - - SLSI_KIC_ATTR_KIC_VERSION_MAJOR, - SLSI_KIC_ATTR_KIC_VERSION_MINOR, - SLSI_KIC_ATTR_TECHNOLOGY_TYPE, - SLSI_KIC_ATTR_SYSTEM_EVENT_CATEGORY, - SLSI_KIC_ATTR_SYSTEM_EVENT, - SLSI_KIC_ATTR_SERVICE_INFO, - SLSI_KIC_ATTR_NUMBER_OF_ENCODED_SERVICES, - SLSI_KIC_ATTR_TEST_RECOVERY_TYPE, - SLSI_KIC_ATTR_TIMESTAMP, - SLSI_KIC_ATTR_FIRMWARE_EVENT_TYPE, - SLSI_KIC_ATTR_FIRMWARE_CONTAINER_TYPE, - SLSI_KIC_ATTR_FIRMWARE_EVENT_CONTAINER_CCP_HOST, - SLSI_KIC_ATTR_TRIGGER_RECOVERY_STATUS, - SLSI_KIC_ATTR_ECHO, - - /* Add attributes here, update the policy below */ - __SLSI_KIC_ATTR_AFTER_LAST, - SLSI_KIC_ATTR_MAX = __SLSI_KIC_ATTR_AFTER_LAST - 1 -}; - - -/* Policy for the attributes */ -static const struct nla_policy slsi_kic_attr_policy[SLSI_KIC_ATTR_MAX + 1] = { - [SLSI_KIC_ATTR_KIC_VERSION_MAJOR] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_KIC_VERSION_MINOR] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_TECHNOLOGY_TYPE] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_SYSTEM_EVENT_CATEGORY] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_SYSTEM_EVENT] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_SERVICE_INFO] = { .type = NLA_NESTED, }, - [SLSI_KIC_ATTR_NUMBER_OF_ENCODED_SERVICES] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_TEST_RECOVERY_TYPE] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_TIMESTAMP] = { .type = NLA_NESTED }, - [SLSI_KIC_ATTR_FIRMWARE_EVENT_TYPE] = { .type = NLA_U16 }, - [SLSI_KIC_ATTR_FIRMWARE_CONTAINER_TYPE] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CONTAINER_CCP_HOST] = { .type = NLA_NESTED }, - [SLSI_KIC_ATTR_TRIGGER_RECOVERY_STATUS] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_ECHO] = { .type = NLA_U32 }, -}; - -/* Policy for the slsi_kic_firmware_event_ccp_host attribute */ -static const struct nla_policy slsi_kic_attr_firmware_event_ccp_host_policy[SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_MAX + 1] = { - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_ID] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_LEVEL] = { .type = NLA_U32 }, -#ifdef __KERNEL__ - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_LEVEL_STRING] = { .type = NLA_STRING, .len = 128 }, -#else - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_LEVEL_STRING] = { .type = NLA_STRING, .maxlen = 128 }, -#endif - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_TIMESTAMP] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_CPU] = { .type = NLA_U32 }, - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_OCCURENCES] = { .type = NLA_U32 }, -#ifdef __KERNEL__ - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_ARG] = { .type = NLA_UNSPEC, - .len = SLSI_KIC_FIRMWARE_EVENT_CCP_HOST_ARG_LENGTH }, -#else - [SLSI_KIC_ATTR_FIRMWARE_EVENT_CCP_HOST_ARG] = { .type = NLA_UNSPEC, - .maxlen = SLSI_KIC_FIRMWARE_EVENT_CCP_HOST_ARG_LENGTH }, -#endif -}; - - -/* Policy for the slsi_kic_service_info attribute */ -static const struct nla_policy slsi_kic_attr_service_info_policy[SLSI_KIC_ATTR_SERVICE_INFO_MAX + 1] = { -#ifdef __KERNEL__ - [SLSI_KIC_ATTR_SERVICE_INFO_VER_STR] = { .type = NLA_STRING, .len = 128 }, -#else - [SLSI_KIC_ATTR_SERVICE_INFO_VER_STR] = { .type = NLA_STRING, .maxlen = 128 }, -#endif - [SLSI_KIC_ATTR_SERVICE_INFO_FW_API_MAJOR] = { .type = NLA_U16 }, - [SLSI_KIC_ATTR_SERVICE_INFO_FW_API_MINOR] = { .type = NLA_U16 }, - [SLSI_KIC_ATTR_SERVICE_INFO_RELEASE_PRODUCT] = { .type = NLA_U16 }, - [SLSI_KIC_ATTR_SERVICE_INFO_HOST_RELEASE_ITERATION] = { .type = NLA_U16 }, - [SLSI_KIC_ATTR_SERVICE_INFO_HOST_RELEASE_CANDIDATE] = { .type = NLA_U16 }, -}; - -/* Policy for the slsi_kic_timestamp attribute */ -static const struct nla_policy slsi_kic_attr_timestamp_policy[SLSI_KIC_ATTR_TIMESTAMP_MAX + 1] = { - [SLSI_KIC_ATTR_TIMESTAMP_TV_SEC] = { .type = NLA_U64 }, - [SLSI_KIC_ATTR_TIMESTAMP_TV_NSEC] = { .type = NLA_U64 }, -}; - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* #ifndef __SLSI_KIC_PRIM_H */ diff --git a/include/scsc/kic/slsi_kic_wifi.h b/include/scsc/kic/slsi_kic_wifi.h deleted file mode 100755 index 8938505efa02..000000000000 --- a/include/scsc/kic/slsi_kic_wifi.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SLSI_KIC_WIFI_H -#define __SLSI_KIC_WIFI_H - -#include - -/** - * struct slsi_kic_wifi_ops - backend description for Wi-Fi service driver ops. - * - * This struct is registered by the Wi-Fi service driver during initilisation - * in order provide Wi-Fi specific services, which can be used by KIC. - * - * All callbacks except where otherwise noted should return 0 on success or a - * negative error code. - * - * @trigger_recovery: Trigger a Wi-Fi firmware subsystem recovery. The variable - * @type specifies the recovery type. - */ -struct slsi_kic_wifi_ops { - int (*trigger_recovery)(void *priv, enum slsi_kic_test_recovery_type type); -}; - -#ifdef CONFIG_SAMSUNG_KIC -/** - * slsi_kic_wifi_ops_register - register wifi_ops with KIC - * - * @priv: Private pointer, which will be included in all calls from KIC. - * @wifi_ops: The wifi_ops to register. - * - * Returns 0 on success or a negative error code. - */ -int slsi_kic_wifi_ops_register(void *priv, struct slsi_kic_wifi_ops *wifi_ops); - -/** - * slsi_kic_wifi_ops_unregister - unregister wifi_ops with KIC - * - * @wifi_ops: The wifi_ops to unregister. - * - * After this call, no more requests can be made, but the call may sleep to wait - * for an outstanding request that is being handled. - */ -void slsi_kic_wifi_ops_unregister(struct slsi_kic_wifi_ops *wifi_ops); - -#else - -#define slsi_kic_wifi_ops_register(a, b) \ - do { \ - (void)(a); \ - (void)(b); \ - } while (0) - -#define slsi_kic_wifi_ops_unregister(a) \ - do { \ - (void)(a); \ - } while (0) - -#endif /* CONFIG_SAMSUNG_KIC */ - -#endif /* #ifndef __SLSI_KIC_WIFI_H */ diff --git a/include/scsc/scsc_log_collector.h b/include/scsc/scsc_log_collector.h deleted file mode 100644 index d2cb179081cf..000000000000 --- a/include/scsc/scsc_log_collector.h +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef __SCSC_LOG_COLLECTOR_H__ -#define __SCSC_LOG_COLLECTOR_H__ - -/* High nibble is Major, Low nibble is Minor */ -#define SCSC_LOG_HEADER_VERSION_MAJOR 0x03 -#define SCSC_LOG_HEADER_VERSION_MINOR 0x00 -/* Magic string. 4 bytes "SCSC"*/ -/* Header version. 1 byte */ -/* Num chunks. 1 byte */ -/* Offset first Chunk. 2 bytes */ -/* Collection reason. 1 byte */ -/* Reserved. 1 byte */ -/* Reason Code . 2 bytes */ -/* Observer present . 1 bytes */ -#define SCSC_LOG_HEADER_SIZE (13) -#define SCSC_LOG_FW_VERSION_SIZE (128) -#define SCSC_LOG_HOST_VERSION_SIZE (64) -#define SCSC_LOG_FAPI_VERSION_SIZE (64) -/* Reserved 2 . 4 byte */ -#define SCSC_LOG_RESERVED_2 3 -/* Ideally header + versions should be 16 bytes aligne*/ -#define SCSC_SUPPORTED_CHUNKS_HEADER 48 - -#define SCSC_LOG_CHUNK_ALIGN 1 -/* First chunk should be aligned */ -#define SCSC_LOG_OFFSET_FIRST_CHUNK (((SCSC_LOG_HEADER_SIZE + SCSC_LOG_FW_VERSION_SIZE + \ - SCSC_LOG_HOST_VERSION_SIZE + SCSC_LOG_FAPI_VERSION_SIZE + \ - SCSC_LOG_RESERVED_2 + SCSC_SUPPORTED_CHUNKS_HEADER) + \ - (SCSC_LOG_CHUNK_ALIGN - 1)) & ~(SCSC_LOG_CHUNK_ALIGN - 1)) -enum scsc_log_reason { - SCSC_LOG_UNKNOWN = 0, - SCSC_LOG_FW_PANIC, - SCSC_LOG_USER, - SCSC_LOG_FW, - SCSC_LOG_DUMPSTATE, - SCSC_LOG_HOST_WLAN, - SCSC_LOG_HOST_BT, - SCSC_LOG_HOST_COMMON, - SCSC_LOG_SYS_ERR, - /* Add others */ -}; - -extern const char *scsc_loc_reason_str[]; - -#define SCSC_CHUNK_DAT_LEN_SIZE 4 -#define SCSC_CHUNK_TYP_LEN_SIZE 4 -#define SCSC_CHUNK_HEADER_SIZE (SCSC_CHUNK_DAT_LEN_SIZE + SCSC_CHUNK_TYP_LEN_SIZE) - -/* CHUNKS WILL COLLECTED ON THIS ORDER - - * SYNC SHOULD BE THE FIRST CHUNK - * LOGRING SHOULD BE THE LAST ONE SO IT COULD CAPTURE COLLECTION ERRORS - */ -enum scsc_log_chunk_type { - SCSC_LOG_CHUNK_SYNC, /* SYNC should be the first chunk to collect */ - SCSC_LOG_MINIMOREDUMP, - /* Add other chunks */ - SCSC_LOG_CHUNK_IMP = 127, - SCSC_LOG_CHUNK_MXL, - SCSC_LOG_CHUNK_UDI, - SCSC_LOG_CHUNK_BT_HCF, - SCSC_LOG_CHUNK_WLAN_HCF, - SCSC_LOG_CHUNK_HIP4_SAMPLER, - SCSC_LOG_RESERVED_COMMON, - SCSC_LOG_RESERVED_BT, - SCSC_LOG_RESERVED_WLAN, - SCSC_LOG_RESERVED_RADIO, - /* Add other chunks */ - SCSC_LOG_CHUNK_LOGRING = 254, - SCSC_LOG_CHUNK_INVALID = 255, -}; - -#define SCSC_LOG_COLLECT_MAX_SIZE (16*1024*1024) - -/* ADD Collection codes here for HOST triggers */ -/* Consider moving the definitions to specific services if required */ - -/* Reason codes for SCSC_LOG_USER */ -#define SCSC_LOG_USER_REASON_PROC 0x0000 -/* Reason codes for SCSC_LOG_DUMPSTATE */ -#define SCSC_LOG_DUMPSTATE_REASON 0x0000 -#define SCSC_LOG_DUMPSTATE_REASON_DRIVERDEBUGDUMP 0x0001 -/* Reason codes for SCSC_LOG_HOST_WLAN */ -#define SCSC_LOG_HOST_WLAN_REASON_DISCONNECT 0x0000 -#define SCSC_LOG_HOST_WLAN_REASON_DISCONNECT_IND 0x0001 -#define SCSC_LOG_HOST_WLAN_REASON_DISCONNECTED_IND 0x0002 -#define SCSC_LOG_HOST_WLAN_REASON_DRIVERDEBUGDUMP 0x0003 -#define SCSC_LOG_HOST_WLAN_REASON_CONNECT_ERR 0x0004 -/* Reason codes for SCSC_LOG_HOST_BT */ -/* Reason codes for SCSC_LOG_HOST_COMMON */ -#define SCSC_LOG_HOST_COMMON_REASON_START 0x0000 -#define SCSC_LOG_HOST_COMMON_REASON_STOP 0x0001 -#define SCSC_LOG_HOST_COMMON_RECOVER_RST 0x0002 - -/* SBL HEADER v 0.0*/ -struct scsc_log_sbl_header { - char magic[4]; - u8 version_major; - u8 version_minor; - u8 num_chunks; - u8 trigger; - u16 offset_data; - char fw_version[SCSC_LOG_FW_VERSION_SIZE]; - char host_version[SCSC_LOG_HOST_VERSION_SIZE]; - char fapi_version[SCSC_LOG_FAPI_VERSION_SIZE]; - u16 reason_code; - bool observer; - u8 reserved2[SCSC_LOG_RESERVED_2]; - char supported_chunks[SCSC_SUPPORTED_CHUNKS_HEADER]; -} __packed; - -struct scsc_log_chunk_header { - char magic[3]; - u8 type; - u32 chunk_size; -} __packed; - -struct scsc_log_collector_client { - char *name; - enum scsc_log_chunk_type type; - int (*collect_init)(struct scsc_log_collector_client *collect_client); - int (*collect)(struct scsc_log_collector_client *collect_client, size_t size); - int (*collect_end)(struct scsc_log_collector_client *collect_client); - void *prv; -}; - -int scsc_log_collector_register_client(struct scsc_log_collector_client *collect_client); -int scsc_log_collector_unregister_client(struct scsc_log_collector_client *collect_client); - -/* Public method to get pointer of SBL RAM buffer. */ -unsigned char *scsc_log_collector_get_buffer(void); - -/* Public method to register FAPI version. */ -void scsc_log_collector_write_fapi(char __user *buf, size_t len); - -/* Public method to notify the presence/absense of observers */ -void scsc_log_collector_is_observer(bool observer); - -void scsc_log_collector_schedule_collection(enum scsc_log_reason reason, u16 reason_code); -int scsc_log_collector_write(char __user *buf, size_t count, u8 align); -#endif /* __SCSC_LOG_COLLECTOR_H__ */ diff --git a/include/scsc/scsc_logring.h b/include/scsc/scsc_logring.h deleted file mode 100644 index 707fc46055fc..000000000000 --- a/include/scsc/scsc_logring.h +++ /dev/null @@ -1,709 +0,0 @@ -/***************************************************************************** - * - * Copyright (c) 2016-2018 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef _SCSC_LOGRING_H_ -#define _SCSC_LOGRING_H_ -#include - -#include -#include -#include -#include - -/* NOTE_CREATING_TAGS: when adding a tag here REMEMBER to add it also - * where required, taking care to maintain the same ordering. - * (Search 4 NOTE_CREATING_TAGS) - * - * You must update "int *scsc_droplevels[]" to match. - */ -enum scsc_logring_tags { - FIRST_TAG, - FIRST_BIN_TAG = FIRST_TAG, - BINARY = FIRST_BIN_TAG, - BIN_WIFI_CTRL_RX, - BIN_WIFI_DATA_RX, - BIN_WIFI_CTRL_TX, - BIN_WIFI_DATA_TX, - LAST_BIN_TAG = BIN_WIFI_DATA_TX, - NO_TAG, - WLBT = NO_TAG, - WIFI_RX, - WIFI_TX, - BT_COMMON, - BT_H4, - BT_FW, - BT_RX, - BT_TX, - CPKTBUFF, - FW_LOAD, - FW_PANIC, - GDB_TRANS, - MIF, - CLK20, - CLK20_TEST, - FM, - FM_TEST, - MX_FILE, - MX_FW, - MX_SAMPLER, - MXLOG_TRANS, - MXMAN, - MXMAN_TEST, - MXMGT_TRANS, - MX_MMAP, - MX_PROC, - PANIC_MON, - PCIE_MIF, - PLAT_MIF, - KIC_COMMON, - WLBTD, - WLOG, - LERNA, - MX_CFG, -#ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY - SLSI_INIT_DEINIT, - SLSI_NETDEV, - SLSI_CFG80211, - SLSI_MLME, - SLSI_SUMMARY_FRAMES, - SLSI_HYDRA, - SLSI_TX, - SLSI_RX, - SLSI_UDI, - SLSI_WIFI_FCQ, - SLSI_HIP, - SLSI_HIP_INIT_DEINIT, - SLSI_HIP_FW_DL, - SLSI_HIP_SDIO_OP, - SLSI_HIP_PS, - SLSI_HIP_TH, - SLSI_HIP_FH, - SLSI_HIP_SIG, - SLSI_FUNC_TRACE, - SLSI_TEST, - SLSI_SRC_SINK, - SLSI_FW_TEST, - SLSI_RX_BA, - SLSI_TDLS, - SLSI_GSCAN, - SLSI_MBULK, - SLSI_FLOWC, - SLSI_SMAPPER, -#endif - TEST_ME, - MAX_TAG = TEST_ME /* keep it last */ -}; - - -#define NODEV_LABEL "" -#define SCSC_SDEV_2_DEV(sdev) \ - (((sdev) && (sdev)->wiphy) ? &((sdev)->wiphy->dev) : NULL) -#define SCSC_NDEV_2_DEV(ndev) \ - ((ndev) ? SCSC_SDEV_2_DEV(((struct netdev_vif *)netdev_priv(ndev))->sdev) : NULL) - -#define SCSC_PREFIX "wlbt: " /* prepended to log statements */ - -#define SCSC_TAG_FMT(tag, fmt) SCSC_PREFIX"[" # tag "]: %-5s: - %s: "fmt -#define SCSC_TAG_DBG_FMT(tag, fmt) SCSC_PREFIX"[" # tag "]: %s: "fmt -#define SCSC_DEV_FMT(fmt) SCSC_PREFIX"%-5s: - %s: "fmt -#define SCSC_DBG_FMT(fmt) SCSC_PREFIX"%s: "fmt - -int scsc_logring_enable(bool logging_enable); - -#ifdef CONFIG_SCSC_PRINTK - -int scsc_printk_tag(int force, int tag, const char *fmt, ...); -int scsc_printk_tag_dev(int force, int tag, struct device *dev, const char *fmt, ...); -int scsc_printk_tag_dev_lvl(int force, int tag, struct device *dev, int lvl, const char *fmt, ...); -int scsc_printk_tag_lvl(int tag, int lvl, const char *fmt, ...); -int scsc_printk_bin(int force, int tag, int dlev, const void *start, size_t len); - -/** - * This fields helps in trimming the behavior respect the kernel ring buffer: - * - NO_FORCE_PRK: the tag-based filtering mechanism is obeyed. - * - FORCE_PRK: the tag-based filtering is bypassed by this macro and message - * always get to the kernel ring buffer - * - NO_ECHO_PRK: disable completely the printk redirect. - */ -#define NO_FORCE_PRK 0 -#define FORCE_PRK 1 -#define NO_ECHO_PRK 2 - -#define SCSC_PRINTK(args ...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - args) - -#define SCSC_PRINTK_TAG(tag, args ...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - args) -#define SCSC_PRINTK_BIN(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, \ - -1, (start), (len)) - -#define SCSC_EMERG(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_EMERG SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_ALERT(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_ALERT SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_CRIT(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_CRIT SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_ERR(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_ERR SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_WARNING(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_WARNING SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_NOTICE(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_NOTICE SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_INFO(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_INFO SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_DEBUG(fmt, args...) scsc_printk_tag(NO_FORCE_PRK, WLBT, \ - KERN_DEBUG SCSC_DBG_FMT(fmt), \ - __func__, ## args) - -#define SCSC_TAG_EMERG(tag, fmt, args...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_EMERG SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_ALERT(tag, fmt, args...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_ALERT SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_CRIT(tag, fmt, args ...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_CRIT SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_ERR(tag, fmt, args...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_ERR SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_WARNING(tag, fmt, args...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_WARNING SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_NOTICE(tag, fmt, args...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_NOTICE SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_INFO(tag, fmt, args...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_INFO SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_DEBUG(tag, fmt, args...) scsc_printk_tag(NO_FORCE_PRK, (tag), \ - KERN_DEBUG SCSC_DBG_FMT(fmt), \ - __func__, ## args) - -#define SCSC_TAG_ERR_SDEV(sdev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_SDEV_2_DEV((sdev)), \ - KERN_ERR SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_WARNING_SDEV(sdev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_SDEV_2_DEV((sdev)), \ - KERN_WARNING SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_INFO_SDEV(sdev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_SDEV_2_DEV((sdev)), \ - KERN_INFO SCSC_DBG_FMT(fmt), \ - __func__, ## args) -#define SCSC_TAG_DEBUG_SDEV(sdev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_SDEV_2_DEV((sdev)), \ - KERN_DEBUG SCSC_DBG_FMT(fmt), \ - __func__, ## args) - -#define SCSC_TAG_ERR_NDEV(ndev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_NDEV_2_DEV((ndev)), \ - KERN_ERR SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) -#define SCSC_TAG_WARNING_NDEV(ndev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_NDEV_2_DEV((ndev)), \ - KERN_WARNING SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) -#define SCSC_TAG_INFO_NDEV(ndev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_NDEV_2_DEV((ndev)), \ - KERN_INFO SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) -#define SCSC_TAG_DEBUG_NDEV(ndev, tag, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), SCSC_NDEV_2_DEV((ndev)), \ - KERN_DEBUG SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) - -#define SCSC_TAG_ERR_DEV(tag, dev, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), dev, \ - KERN_ERR SCSC_DBG_FMT(fmt), \ - __func__, ## args) - -#define SCSC_TAG_WARNING_DEV(tag, dev, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), dev, \ - KERN_WARNING SCSC_DBG_FMT(fmt), \ - __func__, ## args) - -#define SCSC_TAG_INFO_DEV(tag, dev, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), dev, \ - KERN_INFO SCSC_DBG_FMT(fmt), \ - __func__, ## args) - -#define SCSC_TAG_DEBUG_DEV(tag, dev, fmt, args...) \ - scsc_printk_tag_dev(NO_FORCE_PRK, (tag), dev, \ - KERN_DEBUG SCSC_DBG_FMT(fmt), \ - __func__, ## args) - -#define SCSC_ERR_SDEV(sdev, fmt, args...) \ - SCSC_TAG_ERR_SDEV(sdev, WLBT, fmt, ## args) -#define SCSC_WARNING_SDEV(sdev, fmt, args...) \ - SCSC_TAG_WARNING_SDEV(sdev, WLBT, fmt, ## args) -#define SCSC_INFO_SDEV(sdev, fmt, args...) \ - SCSC_TAG_INFO_SDEV(sdev, WLBT, fmt, ## args) - -#define SCSC_ERR_NDEV(ndev, fmt, args...) \ - SCSC_TAG_ERR_NDEV(ndev, WLBT, fmt, ## args) -#define SCSC_WARNING_NDEV(ndev, fmt, args...) \ - SCSC_TAG_WARNING_NDEV(ndev, WLBT, fmt, ## args) -#define SCSC_INFO_NDEV(ndev, fmt, args...) \ - SCSC_TAG_INFO_NDEV(ndev, WLBT, fmt, ## args) - - -#define SCSC_BIN_EMERG(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 0, \ - (start), (len)) -#define SCSC_BIN_ALERT(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 1, \ - (start), (len)) -#define SCSC_BIN_CRIT(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 2, \ - (start), (len)) -#define SCSC_BIN_ERR(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 3, \ - (start), (len)) -#define SCSC_BIN_WARNING(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 4, \ - (start), (len)) -#define SCSC_BIN_NOTICE(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 5, \ - (start), (len)) -#define SCSC_BIN_INFO(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 6, \ - (start), (len)) -#define SCSC_BIN_DEBUG(start, len) scsc_printk_bin(NO_FORCE_PRK, BINARY, 7, \ - (start), (len)) - -#define SCSC_BIN_TAG_EMERG(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 0, \ - (start), (len)) -#define SCSC_BIN_TAG_ALERT(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 1, \ - (start), (len)) -#define SCSC_BIN_TAG_CRIT(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 2, \ - (start), (len)) -#define SCSC_BIN_TAG_ERR(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 3, \ - (start), (len)) -#define SCSC_BIN_TAG_WARNING(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 4, \ - (start), (len)) -#define SCSC_BIN_TAG_NOTICE(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 5, \ - (start), (len)) -#define SCSC_BIN_TAG_INFO(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 6, \ - (start), (len)) -#define SCSC_BIN_TAG_DEBUG(tag, start, len) scsc_printk_bin(NO_FORCE_PRK, (tag), 7, \ - (start), (len)) - - -/* - * These macros forces a redundant copy of their output to kernel log buffer and - * console through standard kernel facilities, NO matter how the tag-based - * filtering is configured and NO matter what the value in - * scsc_redirect_to_printk_droplvl module param. - */ -#define SCSC_PRINTK_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, args) -#define SCSC_PRINTK_TAG_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), args) -#define SCSC_PRINTK_BIN_FF(start, len) scsc_printk_bin(FORCE_PRK, -1, \ - (start), (len)) - -#define SCSC_EMERG_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_EMERG SCSC_PREFIX args) -#define SCSC_ALERT_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_ALERT SCSC_PREFIX args) -#define SCSC_CRIT_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_CRIT SCSC_PREFIX args) -#define SCSC_ERR_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_ERR SCSC_PREFIX args) -#define SCSC_WARNING_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_WARNING SCSC_PREFIX args) -#define SCSC_NOTICE_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_NOTICE SCSC_PREFIX args) -#define SCSC_INFO_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_INFO SCSC_PREFIX args) -#define SCSC_DEBUG_FF(args ...) scsc_printk_tag(FORCE_PRK, WLBT, \ - KERN_DEBUG SCSC_PREFIX args) - -#define SCSC_TAG_EMERG_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_EMERG SCSC_PREFIX args) -#define SCSC_TAG_ALERT_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_ALERT SCSC_PREFIX args) -#define SCSC_TAG_CRIT_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_CRIT SCSC_PREFIX args) -#define SCSC_TAG_ERR_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_ERR SCSC_PREFIX args) -#define SCSC_TAG_WARNING_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_WARNING SCSC_PREFIX args) -#define SCSC_TAG_NOTICE_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_NOTICE SCSC_PREFIX args) -#define SCSC_TAG_INFO_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_INFO SCSC_PREFIX args) -#define SCSC_TAG_DEBUG_FF(tag, args ...) scsc_printk_tag(FORCE_PRK, (tag), \ - KERN_DEBUG SCSC_PREFIX args) - -#define SCSC_BIN_EMERG_FF(start, len) scsc_printk_bin(FORCE_PRK, 0, \ - (start), (len)) -#define SCSC_BIN_ALERT_FF(start, len) scsc_printk_bin(FORCE_PRK, 1, \ - (start), (len)) -#define SCSC_BIN_CRIT_FF(start, len) scsc_printk_bin(FORCE_PRK, 2, \ - (start), (len)) -#define SCSC_BIN_ERR_FF(start, len) scsc_printk_bin(FORCE_PRK, 3, \ - (start), (len)) -#define SCSC_BIN_WARNING_FF(start, len) scsc_printk_bin(FORCE_PRK, 4, \ - (start), (len)) -#define SCSC_BIN_NOTICE_FF(start, len) scsc_printk_bin(FORCE_PRK, 5, \ - (start), (len)) -#define SCSC_BIN_INFO_FF(start, len) scsc_printk_bin(FORCE_PRK, 6, \ - (start), (len)) -#define SCSC_BIN_DEBUG_FF(start, len) scsc_printk_bin(FORCE_PRK, 7, \ - (start), (len)) - -#define SCSC_TAG_LVL(tag, lvl, fmt, args...) \ - scsc_printk_tag_lvl((tag), (lvl), fmt, ## args) - -#define SCSC_TAG_DEV_LVL(tag, lvl, dev, fmt, args...) \ - scsc_printk_tag_dev_lvl(NO_FORCE_PRK, (tag), (dev), (lvl), fmt, ## args) - - -#define SCSC_TAG_DBG1_SDEV(sdev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 7, SCSC_SDEV_2_DEV((sdev)), \ - SCSC_DBG_FMT(fmt), __func__, ## args) - -#define SCSC_TAG_DBG2_SDEV(sdev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 8, SCSC_SDEV_2_DEV((sdev)), \ - SCSC_DBG_FMT(fmt), __func__, ## args) - -#define SCSC_TAG_DBG3_SDEV(sdev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 9, SCSC_SDEV_2_DEV((sdev)), \ - SCSC_DBG_FMT(fmt), __func__, ## args) - -#define SCSC_TAG_DBG4_SDEV(sdev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 10, SCSC_SDEV_2_DEV((sdev)), \ - SCSC_DBG_FMT(fmt), __func__, ## args) - -#define SCSC_TAG_DBG1_NDEV(ndev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 7, SCSC_NDEV_2_DEV((ndev)), SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) - -#define SCSC_TAG_DBG2_NDEV(ndev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 8, SCSC_NDEV_2_DEV((ndev)), SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) - -#define SCSC_TAG_DBG3_NDEV(ndev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 9, SCSC_NDEV_2_DEV((ndev)), SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) - -#define SCSC_TAG_DBG4_NDEV(ndev, tag, fmt, args...) \ - SCSC_TAG_DEV_LVL((tag), 10, SCSC_NDEV_2_DEV((ndev)), SCSC_DEV_FMT(fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), \ - __func__, ## args) - -#define SCSC_TAG_DBG1(tag, fmt, args ...) \ - SCSC_TAG_LVL((tag), 7, fmt, ## args) - -#define SCSC_TAG_DBG2(tag, fmt, args ...) \ - SCSC_TAG_LVL((tag), 8, fmt, ## args) - -#define SCSC_TAG_DBG3(tag, fmt, args ...) \ - SCSC_TAG_LVL((tag), 9, fmt, ## args) - -#define SCSC_TAG_DBG4(tag, fmt, args ...) \ - SCSC_TAG_LVL((tag), 10, fmt, ## args) - -#else /* CONFIG_SCSC_PRINTK */ - -#define SCSC_TAG_LVL(tag, lvl, fmt, args...) \ - do {\ - if ((lvl) < 7)\ - printk_emit(0, (lvl), NULL, 0, fmt, ## args);\ - } while (0) - -#define SCSC_TAG_DEV_LVL(tag, lvl, dev, fmt, args...) \ - do {\ - if ((lvl) < 7)\ - dev_printk_emit((lvl), (dev), fmt, ## args);\ - } while (0) - -#define SCSC_PRINTK(fmt, args ...) printk(SCSC_PREFIX fmt, ## args) -#define SCSC_PRINTK_TAG(tag, fmt, args ...) printk(SCSC_PREFIX "[" # tag "] "fmt, ## args) -#define SCSC_PRINTK_BIN(start, len) print_hex_dump(KERN_INFO, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_PRINTK_FF(fmt, args ...) printk(SCSC_PREFIX fmt, ## args) -#define SCSC_PRINTK_TAG_FF(tag, fmt, args ...) printk(SCSC_PREFIX"[" # tag "] "fmt, ## args) -#define SCSC_PRINTK_BIN_FF(start, len) print_hex_dump(KERN_INFO, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_EMERG(fmt, args...) pr_emerg(SCSC_DBG_FMT(fmt), __func__, ## args) -#define SCSC_ALERT(fmt, args...) pr_alert(SCSC_DBG_FMT(fmt), __func__, ## args) -#define SCSC_CRIT(fmt, args...) pr_crit(SCSC_DBG_FMT(fmt), __func__, ## args) -#define SCSC_ERR(fmt, args...) pr_err(SCSC_DBG_FMT(fmt), __func__, ## args) -#define SCSC_WARNING(fmt, args...) pr_warn(SCSC_DBG_FMT(fmt), __func__, ## args) -#define SCSC_NOTICE(fmt, args...) pr_notice(SCSC_DBG_FMT(fmt), __func__, ## args) -#define SCSC_INFO(fmt, args...) pr_info(SCSC_DBG_FMT(fmt), __func__, ## args) -#define SCSC_DEBUG(args...) do {} while (0) - -/* Reverting to pr_* keeping the [tag] */ -#define SCSC_TAG_EMERG(tag, fmt, args...) \ - pr_emerg(SCSC_TAG_DBG_FMT(tag, fmt), __func__, ## args) -#define SCSC_TAG_ALERT(tag, fmt, args...) \ - pr_alert(SCSC_TAG_DBG_FMT(tag, fmt), __func__, ## args) -#define SCSC_TAG_CRIT(tag, fmt, args...) \ - pr_crit(SCSC_TAG_DBG_FMT(tag, fmt), __func__, ## args) -#define SCSC_TAG_ERR(tag, fmt, args...) \ - pr_err(SCSC_TAG_DBG_FMT(tag, fmt), __func__, ## args) -#define SCSC_TAG_WARNING(tag, fmt, args...) \ - pr_warn(SCSC_TAG_DBG_FMT(tag, fmt), __func__, ## args) -#define SCSC_TAG_NOTICE(tag, fmt, args...) \ - pr_notice(SCSC_TAG_DBG_FMT(tag, fmt), __func__, ## args) -#define SCSC_TAG_INFO(tag, fmt, args...) \ - pr_info(SCSC_TAG_DBG_FMT(tag, fmt), __func__, ## args) -#define SCSC_TAG_DEBUG(tag, fmt, args...) do {} while (0) - - -#define SCSC_BIN_EMERG(start, len) print_hex_dump(KERN_EMERG, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_ALERT(start, len) print_hex_dump(KERN_ALERT, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_CRIT(start, len) print_hex_dump(KERN_CRIT, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_ERR(start, len) print_hex_dump(KERN_ERR, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_WARNING(start, len) print_hex_dump(KERN_WARNING, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_NOTICE(start, len) print_hex_dump(KERN_NOTICE, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_INFO(start, len) print_hex_dump(KERN_INFO, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_DEBUG(start, len) do {} while (0) - - -#define SCSC_BIN_TAG_EMERG(tag, start, len) print_hex_dump(KERN_EMERG, \ - SCSC_PREFIX"[" # tag "]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_TAG_ALERT(tag, start, len) print_hex_dump(KERN_ALERT, \ - SCSC_PREFIX"[" # tag "]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_TAG_CRIT(tag, start, len) print_hex_dump(KERN_CRIT, \ - SCSC_PREFIX"[" # tag "]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_TAG_ERR(tag, start, len) print_hex_dump(KERN_ERR, \ - SCSC_PREFIX"[" # tag "]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_TAG_WARNING(tag, start, len) print_hex_dump(KERN_WARNING, \ - SCSC_PREFIX"[" # tag "]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_TAG_NOTICE(tag, start, len) print_hex_dump(KERN_NOTICE, \ - SCSC_PREFIX"[" # tag "]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_TAG_INFO(tag, start, len) print_hex_dump(KERN_INFO, \ - SCSC_PREFIX"[" # tag "]->|", \ - DUMP_PREFIX_NONE, \ - 16, 1, start, \ - len, false) - -#define SCSC_BIN_TAG_DEBUG(tag, start, len) do {} while (0) - - -#define SCSC_EMERG_FF(args ...) pr_emerg(SCSC_PREFIX args) -#define SCSC_ALERT_FF(args ...) pr_alert(SCSC_PREFIX args) -#define SCSC_CRIT_FF(args ...) pr_crit(SCSC_PREFIX args) -#define SCSC_ERR_FF(args ...) pr_err(SCSC_PREFIX args) -#define SCSC_WARNING_FF(args ...) pr_warn(SCSC_PREFIX args) -#define SCSC_NOTICE_FF(args ...) pr_notice(SCSC_PREFIX args) -#define SCSC_INFO_FF(args ...) pr_info(SCSC_PREFIX args) -#define SCSC_DEBUG_FF(args ...) do {} while (0) - - -#define SCSC_TAG_EMERG_FF(tag, fmt, args ...) pr_emerg(SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) -#define SCSC_TAG_ALERT_FF(tag, fmt, args ...) pr_alert(SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) -#define SCSC_TAG_CRIT_FF(tag, fmt, args ...) pr_crit(SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) -#define SCSC_TAG_ERR_FF(tag, fmt, args ...) pr_err(SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) -#define SCSC_TAG_WARNING_FF(tag, fmt, args ...) pr_warn(SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) -#define SCSC_TAG_NOTICE_FF(tag, fmt, args ...) pr_notice(SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) -#define SCSC_TAG_INFO_FF(tag, fmt, args ...) pr_info(SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) -#define SCSC_TAG_DEBUG_FF(tag, fmt, args ...) do {} while (0) - -#define SCSC_BIN_EMERG_FF(start, len) print_hex_dump(KERN_EMERG, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_ALERT_FF(start, len) print_hex_dump(KERN_ALERT, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_CRIT_FF(start, len) print_hex_dump(KERN_CRIT, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_ERR_FF(start, len) print_hex_dump(KERN_ERR, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_WARNING_FF(start, len) print_hex_dump(KERN_WARNING, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_NOTICE_FF(start, len) print_hex_dump(KERN_NOTICE, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_INFO_FF(start, len) print_hex_dump(KERN_INFO, \ - SCSC_PREFIX"[BINARY]->|", \ - DUMP_PREFIX_ADDRESS, \ - 16, 4, start, \ - len, true) - -#define SCSC_BIN_DEBUG_FF(start, len) do {} while (0) - - -#define SCSC_TAG_ERR_SDEV(sdev, tag, fmt, args...) \ - dev_err(SCSC_SDEV_2_DEV((sdev)), SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) - -#define SCSC_TAG_WARNING_SDEV(sdev, tag, fmt, args...) \ - dev_warn(SCSC_SDEV_2_DEV((sdev)), SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) - -#define SCSC_TAG_INFO_SDEV(sdev, tag, fmt, args...) \ - dev_info(SCSC_SDEV_2_DEV((sdev)), SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) - -#define SCSC_TAG_DEBUG_SDEV(sdev, tag, fmt, args...) do {} while (0) - - -#define SCSC_TAG_ERR_NDEV(ndev, tag, fmt, args...) \ - dev_err(SCSC_NDEV_2_DEV((ndev)), SCSC_TAG_FMT(tag, fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), __func__, ## args) -#define SCSC_TAG_WARNING_NDEV(ndev, tag, fmt, args...) \ - dev_warn(SCSC_NDEV_2_DEV((ndev)), SCSC_TAG_FMT(tag, fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), __func__, ## args) -#define SCSC_TAG_INFO_NDEV(ndev, tag, fmt, args...) \ - dev_info(SCSC_NDEV_2_DEV((ndev)), SCSC_TAG_FMT(tag, fmt), \ - ((ndev) ? netdev_name(ndev) : NODEV_LABEL), __func__, ## args) - -#define SCSC_TAG_DEBUG_NDEV(ndev, tag, fmt, args...) do {} while (0) - -#define SCSC_TAG_ERR_DEV(tag, dev, fmt, args...) \ - dev_err(dev, SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) - -#define SCSC_TAG_WARNING_DEV(tag, dev, fmt, args...) \ - dev_warn(dev, SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) - -#define SCSC_TAG_INFO_DEV(tag, dev, fmt, args...) \ - dev_info(dev, SCSC_TAG_DBG_FMT(tag, fmt), \ - __func__, ## args) - -#define SCSC_TAG_DEBUG_DEV(tag, dev, fmt, args...) do {} while (0) - -#define SCSC_ERR_SDEV(sdev, fmt, args...) \ - SCSC_TAG_ERR_SDEV(sdev, WLBT, fmt, ## args) -#define SCSC_WARNING_SDEV(sdev, fmt, args...) \ - SCSC_TAG_WARNING_SDEV(sdev, WLBT, fmt, ## args) -#define SCSC_INFO_SDEV(sdev, fmt, args...) \ - SCSC_TAG_INFO_SDEV(sdev, WLBT, fmt, ## args) - -#define SCSC_ERR_NDEV(ndev, fmt, args...) \ - SCSC_TAG_ERR_NDEV(ndev, WLBT, fmt, ## args) -#define SCSC_WARNING_NDEV(ndev, fmt, args...) \ - SCSC_TAG_WARNING_NDEV(ndev, WLBT, fmt, ## args) -#define SCSC_INFO_NDEV(ndev, fmt, args...) \ - SCSC_TAG_INFO_NDEV(ndev, WLBT, fmt, ## args) - - -#define SCSC_TAG_DBG1_SDEV(sdev, tag, fmt, args...) do {} while (0) -#define SCSC_TAG_DBG2_SDEV(sdev, tag, fmt, args...) do {} while (0) -#define SCSC_TAG_DBG3_SDEV(sdev, tag, fmt, args...) do {} while (0) -#define SCSC_TAG_DBG4_SDEV(sdev, tag, fmt, args...) do {} while (0) - -#define SCSC_TAG_DBG1_NDEV(ndev, tag, fmt, args...) do {} while (0) -#define SCSC_TAG_DBG2_NDEV(ndev, tag, fmt, args...) do {} while (0) -#define SCSC_TAG_DBG3_NDEV(ndev, tag, fmt, args...) do {} while (0) -#define SCSC_TAG_DBG4_NDEV(ndev, tag, fmt, args...) do {} while (0) - -#define SCSC_TAG_DBG1(tag, fmt, args ...) do {} while (0) -#define SCSC_TAG_DBG2(tag, fmt, args ...) do {} while (0) -#define SCSC_TAG_DBG3(tag, fmt, args ...) do {} while (0) -#define SCSC_TAG_DBG4(tag, fmt, args ...) do {} while (0) - -#endif - -#endif /* _SCSC_LOGRING_H_ */ diff --git a/include/scsc/scsc_mifram.h b/include/scsc/scsc_mifram.h deleted file mode 100644 index 671028d2f5e0..000000000000 --- a/include/scsc/scsc_mifram.h +++ /dev/null @@ -1,16 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef _SCSC_MIFRAM_H -#define _SCSC_MIFRAM_H - -/* - * Portable reference to DRAM address. - * In practice this should native R4 relative address. - */ - -typedef s32 scsc_mifram_ref; -#endif diff --git a/include/scsc/scsc_mx.h b/include/scsc/scsc_mx.h deleted file mode 100755 index cf4da45383e8..000000000000 --- a/include/scsc/scsc_mx.h +++ /dev/null @@ -1,531 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - ****************************************************************************/ - -#ifndef _SCSC_CORE_H -#define _SCSC_CORE_H - -#include -#include -#include "scsc_mifram.h" - -#define SCSC_PANIC_CODE_FW 0 -#define SCSC_PANIC_CODE_HOST 1 - -#define SCSC_FW_EVENT_FAILURE 0 -#define SCSC_FW_EVENT_MOREDUMP_COMPLETE 1 - -/** The following flags define the pools that can used for memory allocation. - * To be used with scsc_mx_service_mifram_alloc_extended **/ -/* Standard memory allocation */ -#define MIFRAMMAN_MEM_POOL_GENERIC 1 -/* Used for buffers containing logs that will not be dumped by moredump */ -#define MIFRAMMAN_MEM_POOL_LOGGING 2 - -struct device; -struct firmware; -struct scsc_mx; - -enum scsc_service_id { - SCSC_SERVICE_ID_NULL = 0, - SCSC_SERVICE_ID_WLAN = 1, - SCSC_SERVICE_ID_BT = 2, - SCSC_SERVICE_ID_ANT = 3, - SCSC_SERVICE_ID_R4DBG = 4, - SCSC_SERVICE_ID_ECHO = 5, - SCSC_SERVICE_ID_DBG_SAMPLER = 6, - SCSC_SERVICE_ID_CLK20MHZ = 7, - SCSC_SERVICE_ID_FM = 8, - SCSC_SERVICE_ID_INVALID = 0xff, -}; - -#ifdef CONFIG_SCSC_QOS -#define SCSC_SERVICE_TOTAL 9 -#endif - -enum scsc_module_client_reason { - SCSC_MODULE_CLIENT_REASON_HW_PROBE = 0, - SCSC_MODULE_CLIENT_REASON_HW_REMOVE = 1, - SCSC_MODULE_CLIENT_REASON_RECOVERY = 2, - SCSC_MODULE_CLIENT_REASON_INVALID = 0xff, -}; - -#ifdef CONFIG_SCSC_QOS -enum scsc_qos_config { - SCSC_QOS_DISABLED = 0, - SCSC_QOS_MIN = 1, - SCSC_QOS_MED = 2, - SCSC_QOS_MAX = 3, -}; -#endif - -/* SYSTEM ERROR SUB-SYSTEMS */ -#define SYSERR_SUBSYS_COMMON (0) -#define SYSERR_SUBSYS_BT (1) -#define SYSERR_SUBSYS_WLAN (2) -#define SYSERR_SUBSYS_HOST (8) - - -/* SYSTEM ERROR levels */ - -/* System Error level 1 - * Minor warning from firmware - * Should not be escalted by driver - */ -#define MX_SYSERR_LEVEL_1 (1) - -/* System Error level 2 - * More severe warning from firmware - * May be escalated by driver - */ -#define MX_SYSERR_LEVEL_2 (2) - -/* System Error level 2 - * Minor error handled in firmware - * may be escalated by driver - */ -#define MX_SYSERR_LEVEL_3 (3) - -/* System Error level 3 - * More severe error handled in firmware - * May be escalated by driver - */ -#define MX_SYSERR_LEVEL_4 (4) - -/* System Error level 5 - * Firmware requested service restart - * May be escalated by driver - */ -#define MX_SYSERR_LEVEL_5 (5) - -/* System Error level 5 - * Firmware requested service restart (firmware may have restarted some hardware) - * May be escalated by driver - */ -#define MX_SYSERR_LEVEL_6 (6) - -/* System Error level 7 - * Firmware halt and full restart required - */ -#define MX_SYSERR_LEVEL_7 (7) - -/* Null error code */ -#define MX_NULL_SYSERR (0xFFFF) - -/* Details for decoding */ -#define SYSERR_SUB_CODE_POSN (0) -#define SYSERR_SUB_CODE_MASK (0xFFFF) -#define SYSERR_SUB_SYSTEM_POSN (12) -#define SYSERR_SUB_SYSTEM_MASK (0xF) -#define SYSERR_LEVEL_POSN (24) -#define SYSERR_LEVEL_MASK (0xF) -#define SYSERR_TYPE_POSN (28) -#define SYSERR_TYPE_MASK (0xFF) -#define SYSERR_SUB_SYSTEM_HOST (8) - - -/* Core Driver Module registration */ -struct scsc_mx_module_client { - char *name; - void (*probe)(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason); - void (*remove)(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason); -}; - -/* Service Client interface */ - -/* Decoded syserr_code */ -struct mx_syserr_decode { - u8 subsys; - u8 level; - u16 type; - u16 subcode; -}; - -struct scsc_service_client; - -struct scsc_service_client { - /** Called on Maxwell System Error. The Client should use its internal state information - * and the information provided by this call to return an appropriate recovery level - * which must be greater than or equal to that passed in as parameter within the - * mx_syserr_decode structure. - */ - u8 (*failure_notification)(struct scsc_service_client *client, struct mx_syserr_decode *err); - /** Called on Maxwell failure requiring a service restart or full chip restart. - * The level within the mx_syserr_decode structure indicates the recover level taking place. - * The Client should Stop all SDRAM & MIF Mailbox access as fast as possible - * and inform the Manager by calling client_stopped(). The boolean return value - * indicates that this failure should trigger an slsi_send_hanged_vendor_event - * if WLAN is active (common code will ensure this happens by passing scsc_syserr_code - * parameter with a value other than MX_NULL_SYSERR when failure_reset is called subsequently) - */ - bool (*stop_on_failure_v2)(struct scsc_service_client *client, struct mx_syserr_decode *err); - /* Old version to be depricated */ - void (*stop_on_failure)(struct scsc_service_client *client); - /** Called when Maxwell failure has been handled and the Maxwell has been - * reset if the level has demanded it. The Client should assume that any Maxwell - * resources it held are invalid. If a scsc_syserr_code other than MX_NULL_SYSERR is provided, - * then this may be propogated by the WLAN driver as a slsi_send_hanged_vendor_event - * to notify the host of the failure and its cause - */ - void (*failure_reset_v2)(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code); - /* Old version to be depricated */ - void (*failure_reset)(struct scsc_service_client *client, u16 scsc_panic_code); - /* called when AP processor is going into suspend. */ - int (*suspend)(struct scsc_service_client *client); - /* called when AP processor has resumed */ - int (*resume)(struct scsc_service_client *client); - /* called when log collection has been triggered */ - void (*log)(struct scsc_service_client *client, u16 reason); -}; - -/* - * This must be used by FM Radio Service only. Other services must not use it. - * FM Radio client must allocate memory for this structure using scsc_mx_service_mifram_alloc() - * and pass this structure as a ref parameter to scsc_mx_service_start(). - * The version of fm_ldo_conf (the LDO configuration structure) must be written - * to the version field by the FM Radio Service and confirmed to match the define by the firmware. - * Increment the version (FM_LDO_CONFIG_VERSION) when changing the layout of the structure. - */ -#define FM_LDO_CONFIG_VERSION 0 - -struct fm_ldo_conf { - uint32_t version; /* FM_LDO_CONFIG_VERSION */ - uint32_t ldo_on; -}; - -/* Parameters to pass from FM radio client driver to WLBT drivers */ -struct wlbt_fm_params { - u32 freq; /* Frequency (Hz) in use by FM radio */ -}; - - -#define PANIC_RECORD_SIZE 64 -#define PANIC_RECORD_DUMP_BUFFER_SZ 4096 - -/* WARNING: THIS IS INTERRUPT CONTEXT! - * here: some serious warnings about not blocking or doing anything lengthy at all - */ -typedef void (*scsc_mifintrbit_handler)(int which_bit, void *data); - -/* - * Core Module Inteface - */ -int scsc_mx_module_register_client_module(struct scsc_mx_module_client *module_client); -void scsc_mx_module_unregister_client_module(struct scsc_mx_module_client *module_client); -int scsc_mx_module_reset(void); - -/* - * Core Instance interface - */ -/** 1st thing to do is call open and return service managment interface*/ -struct scsc_service *scsc_mx_service_open(struct scsc_mx *mx, enum scsc_service_id id, struct scsc_service_client *client, int *status); - -/* - * Service interface - */ -/** pass a portable dram reference and returns kernel pointer (basically is dealing with the pointers) */ -void *scsc_mx_service_mif_addr_to_ptr(struct scsc_service *service, scsc_mifram_ref ref); -void *scsc_mx_service_mif_addr_to_phys(struct scsc_service *service, scsc_mifram_ref ref); -int scsc_mx_service_mif_ptr_to_addr(struct scsc_service *service, void *mem_ptr, scsc_mifram_ref *ref); - -int scsc_mx_service_start(struct scsc_service *service, scsc_mifram_ref ref); -int scsc_mx_service_stop(struct scsc_service *service); -int scsc_mx_service_close(struct scsc_service *service); -int scsc_mx_service_mif_dump_registers(struct scsc_service *service); - -/** Signal a failure detected by the Client. This will trigger the systemwide - * MX_SYSERR_LEVEL_7 failure handling procedure: _All_ Clients will be called back via - * their stop_on_failure() handler as a side-effect. */ -void scsc_mx_service_service_failed(struct scsc_service *service, const char *reason); - -/* MEMORY Interface*/ -/** Allocate a contiguous block of SDRAM accessible to Client Driver. The memory will be allocated - * from generic pool (MIFRAMMAN_MEM_POOL_GENERIC) */ -int scsc_mx_service_mifram_alloc(struct scsc_service *service, size_t nbytes, scsc_mifram_ref *ref, u32 align); -/* Same as scsc_mx_service_mifram_alloc but allows to specify flags (MIFRAMMAN_MEM_POOL_XX). - * So, for example, to allocate memory from the logging pool use MIFRAMMAN_MEM_POOL_LOGGING. */ -int scsc_mx_service_mifram_alloc_extended(struct scsc_service *service, size_t nbytes, scsc_mifram_ref *ref, u32 align, uint32_t flags); -struct scsc_bt_audio_abox *scsc_mx_service_get_bt_audio_abox(struct scsc_service *service); -struct mifabox *scsc_mx_service_get_aboxram(struct scsc_service *service); -/** Free a contiguous block of SDRAM */ -void scsc_mx_service_mifram_free(struct scsc_service *service, scsc_mifram_ref ref); -void scsc_mx_service_mifram_free_extended(struct scsc_service *service, scsc_mifram_ref ref, uint32_t flags); - -/* MBOX Interface */ -/** Allocate n contiguous mailboxes. Outputs index of first mbox, returns FALSE if can’t allocate n contiguous mailboxes. */ -bool scsc_mx_service_alloc_mboxes(struct scsc_service *service, int n, int *first_mbox_index); -/** Free n contiguous mailboxes. */ -void scsc_service_free_mboxes(struct scsc_service *service, int n, int first_mbox_index); - -/** Get kernel-space pointer to a mailbox. - * The pointer can be cached as it is guaranteed not to change between service start & stop. - **/ -u32 *scsc_mx_service_get_mbox_ptr(struct scsc_service *service, int mbox_index); - -/* IRQ Interface */ -/* Getters/Setters */ - -/* From R4/M4 */ -int scsc_service_mifintrbit_bit_mask_status_get(struct scsc_service *service); -int scsc_service_mifintrbit_get(struct scsc_service *service); -void scsc_service_mifintrbit_bit_clear(struct scsc_service *service, int which_bit); -void scsc_service_mifintrbit_bit_mask(struct scsc_service *service, int which_bit); -void scsc_service_mifintrbit_bit_unmask(struct scsc_service *service, int which_bit); - -/* To R4/M4 */ -enum scsc_mifintr_target { - SCSC_MIFINTR_TARGET_R4 = 0, - SCSC_MIFINTR_TARGET_M4 = 1 -}; - -void scsc_service_mifintrbit_bit_set(struct scsc_service *service, int which_bit, enum scsc_mifintr_target dir); - -/* Register an interrupt handler -TOHOST direction. - * Function returns the IRQ associated , -EIO if all interrupts have been assigned */ -int scsc_service_mifintrbit_register_tohost(struct scsc_service *service, scsc_mifintrbit_handler handler, void *data); -/* Unregister an interrupt handler associated with a bit -TOHOST direction */ -int scsc_service_mifintrbit_unregister_tohost(struct scsc_service *service, int which_bit); - -/* Get an interrupt bit associated with the target (R4/M4) -FROMHOST direction - * Function returns the IRQ bit associated , -EIO if error */ -int scsc_service_mifintrbit_alloc_fromhost(struct scsc_service *service, enum scsc_mifintr_target dir); -/* Free an interrupt bit associated with the target (R4/M4) -FROMHOST direction - * Function returns the 0 if succedes , -EIO if error */ -int scsc_service_mifintrbit_free_fromhost(struct scsc_service *service, int which_bit, enum scsc_mifintr_target dir); -/* - * Return a kernel device associated 1:1 with the Maxwell instance. - * This is published only for the purpose of associating service drivers - * with a Maxwell instance for logging purposes. Clients should not make - * any assumptions about the device type. In some configurations this may - * be the associated host-interface device (AXI/PCIe), - * but this may change in future. - */ -struct device *scsc_service_get_device(struct scsc_service *service); -struct device *scsc_service_get_device_by_mx(struct scsc_mx *mx); - -int scsc_service_force_panic(struct scsc_service *service); - -/* - * API to share /sys/wifi kobject between core and wifi driver modules. - * Depending upon the order of loading respective drivers, a kobject is - * created and shared with the other driver. This convoluted implementation - * is required as we need the common kobject associated with "/sys/wifi" directory - * when creating a file underneth. core driver (mxman.c) need to create "memdump" - * and wifi driver (dev.c,mgt.c) needs to create "mac_addr" files respectively. - */ -struct kobject *mxman_wifi_kobject_ref_get(void); -void mxman_wifi_kobject_ref_put(void); - -#ifdef CONFIG_SCSC_SMAPPER -/* SMAPPER Interface */ -/* Configure smapper. Function should configure smapper FW memory map, range, and granularity */ -void scsc_service_mifsmapper_configure(struct scsc_service *service, u32 granularity); -/* Allocate large/small entries bank. Outputs index of bank, returns -EIO if can’t allocate any banks. */ -/* Function also returns by the numbers of entries that could be used in the bank as the number of entries - * is HW dependent (entries/granurality/memory window in FW) - */ -int scsc_service_mifsmapper_alloc_bank(struct scsc_service *service, bool large_bank, u32 entry_size, u16 *entries); -/* Free large/small entries bank */ -int scsc_service_mifsmapper_free_bank(struct scsc_service *service, u8 bank); -/* Get number entries, returns error if entries have not been allocated */ -int scsc_service_mifsmapper_get_entries(struct scsc_service *service, u8 bank, u8 num_entries, u8 *entries); -/* Free number entries, returns error if entries have not been allocated */ -int scsc_service_mifsmapper_free_entries(struct scsc_service *service, u8 bank, u8 num_entries, u8 *entries); -/* Program SRAM entry */ -int scsc_service_mifsmapper_write_sram(struct scsc_service *service, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr); -u32 scsc_service_mifsmapper_get_bank_base_address(struct scsc_service *service, u8 bank); -/* Get SMAPPER aligment */ -u16 scsc_service_get_alignment(struct scsc_service *service); -#endif - -#ifdef CONFIG_SCSC_QOS -int scsc_service_pm_qos_add_request(struct scsc_service *service, enum scsc_qos_config config); -int scsc_service_pm_qos_update_request(struct scsc_service *service, enum scsc_qos_config config); -int scsc_service_pm_qos_remove_request(struct scsc_service *service); -#endif - -/* MXLOGGER API */ -/* If there is no service/mxman associated, register the observer as global (will affect all the mx instanes)*/ -/* Users of these functions should ensure that the registers/unregister functions are balanced (i.e. if observer is registed as global, - * it _has_ to unregister as global) */ -int scsc_service_register_observer(struct scsc_service *service, char *name); -/* Unregister an observer */ -int scsc_service_unregister_observer(struct scsc_service *service, char *name); - -/* Reads a configuration file into memory. - * - * Path is relative to the currently selected firmware configuration - * subdirectory. - * Returns pointer to data or NULL if file not found. - * Call mx140_file_release_conf()to release the memory. - */ -int mx140_file_request_conf(struct scsc_mx *mx, const struct firmware **conf, const char *config_path, const char *filename); - -/* Reads a debug configuration file into memory. - * - * Path is relative to the currently selected firmware configuration - * subdirectory. - * Returns pointer to data or NULL if file not found. - * Call mx140_file_release_conf()to release the memory. - */ -int mx140_file_request_debug_conf(struct scsc_mx *mx, const struct firmware **conf, const char *config_path); - -/* Read device configuration file into memory. - * - * Path is relative to the device configuration directory. - * Returns pointer to data or NULL if file not found. - * Call mx140_file_release_conf() to release the memory. - * This call is only used for configuration files that are - * device instance specific (e.g. mac addresses) - */ -int mx140_file_request_device_conf(struct scsc_mx *mx, const struct firmware **conf, const char *config_path); - -/* Release configuration file memory - * - * If conf is NULL, has no effect. - */ -void mx140_file_release_conf(struct scsc_mx *mx, const struct firmware *conf); - -/* Read device configuration file into memory. - * - * Path is absolute. - * Returns pointer to data or NULL if file not found. - * Call mx140_release_file() to release the memory. - */ -int mx140_request_file(struct scsc_mx *mx, char *path, const struct firmware **firmp); - -/* Release configuration file memory allocated with mx140_request_file() - * - * If firmp is NULL, has no effect. - */ -int mx140_release_file(struct scsc_mx *mx, const struct firmware *firmp); - -/* 20 MHz clock API. - * The mx140 device uses a clock that is also required by the USB driver. - * This API allows the USB/clock driver to inform the mx140 driver that the - * clock is required and that it must boot and/or keep the clock running. - */ - -enum mx140_clk20mhz_status { - MX140_CLK_SUCCESS = 0, /* Returned successfully */ - MX140_CLK_STARTED, /* mx140 has started the clock */ - MX140_CLK_STOPPED, /* mx140 has stopped the clock */ - MX140_CLK_NOT_STARTED, /* failed to start the clock */ - MX140_CLK_NOT_STOPPED, /* failed to stop the clock */ - MX140_CLK_ASYNC_FAIL, /* mx140 failure, async call */ -}; - -/* Register for 20 MHz clock API callbacks - * - * Parameters: - * client_cb: - * If client provides non-NULL client_cb, the request is asynchronous and - * the client will be called back when the clock service is started. - * If client_cb is NULL, the request is blocking. - * data: - * opaque context for the client, and will be passed back in any callback - * - * Note it is possible that the callback may be made in the context of the - * calling request/release function. - * - * Returns 0 on success - */ -int mx140_clk20mhz_register(void (*client_cb)(void *data, enum mx140_clk20mhz_status event), void *data); - -/* Unregister for 20 MHz clock API callbacks. - * After this call is made, the mx140 driver will no longer call back. - */ -void mx140_clk20mhz_unregister(void); - -/* Client request that the clock be available. - * - * If a callback was installed via mx140_clk20mhz_register(), the mx140 driver - * will call back when the clock is available. If no callback was installed, - * the request is blocking and will return when the clock is running. - * - * Returns: - * mx140_clk20mhz_status if a blocking attempt was made to start the clock, - * MX140_CLK_SUCCESS if the request will happen asynchronously, or, - * -ve error code on other error. - * - */ -int mx140_clk20mhz_request(void); - -/* Client informs that the clock is no longer needed - * - * Returns: - * mx140_clk20mhz_status if a blocking attempt was made to stop the clock, - * MX140_CLK_SUCCESS if the request will happen asynchronously, or, - * -ve error code on other error. - */ -int mx140_clk20mhz_release(void); - - -/* Client requests that FM LDO be available. - * - * Returns: - * 0 on success or -ve error code on error. - * - */ -int mx250_fm_request(void); - - -/* Client informs that the LDO is no longer needed - * - * Returns: - * 0 on success or -ve error code on error. - */ -int mx250_fm_release(void); - - -/* FM client informs of parameter change. - * - * mx250_fm_request() must have been called first. - * - * Returns: - * None - */ -void mx250_fm_set_params(struct wlbt_fm_params *info); - -/* - * for set test mode. - * - */ -bool slsi_is_rf_test_mode_enabled(void); - -int mx140_log_dump(void); - -void mxman_get_fw_version(char *version, size_t ver_sz); -void mxman_get_driver_version(char *version, size_t ver_sz); - -int mxman_register_firmware_notifier(struct notifier_block *nb); -int mxman_unregister_firmware_notifier(struct notifier_block *nb); - -/* Status of WLBT autorecovery on the platform - * - * Returns: - * false - enabled, true disabled - */ -bool mxman_recovery_disabled(void); - -/* function to provide string representation of uint8 trigger code */ -static inline const char *scsc_get_trigger_str(int code) -{ - switch (code) { - case 1: return "scsc_log_fw_panic"; - case 2: return "scsc_log_user"; - case 3: return "scsc_log_fw"; - case 4: return "scsc_log_dumpstate"; - case 5: return "scsc_log_host_wlan"; - case 6: return "scsc_log_host_bt"; - case 7: return "scsc_log_host_common"; - case 8: return "scsc_log_sys_error"; - case 0: - default: - return "unknown"; - } -}; - -#endif diff --git a/include/scsc/scsc_release.h b/include/scsc/scsc_release.h deleted file mode 100644 index bf200ef17a3e..000000000000 --- a/include/scsc/scsc_release.h +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved - * - *****************************************************************************/ - -#ifndef _SCSC_RELEASE_H -#define _SCSC_RELEASE_H - -#ifdef CONFIG_SOC_EXYNOS3830 -#define SCSC_RELEASE_SOLUTION "mx152" -#elif defined(CONFIG_SOC_EXYNOS9630) -#define SCSC_RELEASE_SOLUTION "mx450" -#elif defined(CONFIG_SOC_EXYNOS9610) -#define SCSC_RELEASE_SOLUTION "mx250" -#else -#define SCSC_RELEASE_SOLUTION "wlbt" -#endif - - - -#define SCSC_RELEASE_PRODUCT 10 -#define SCSC_RELEASE_ITERATION 5 -#define SCSC_RELEASE_CANDIDATE 1 - -#define SCSC_RELEASE_POINT 1 - -#endif - -