patches: add c3 (remove userspace /dev/bes2600 cdev interface)
Fourth stacked patch in the BESser staging-prep series.
remove-chardev-user-interface/
0001-bes2600-remove-userspace-dev-bes2600-character-devic.patch
519-line deletion of the /dev/bes2600 char-device surface:
- open/read/write/release fops and the bes2600_chardev_fops instance
- bes2600_op_* command handlers + bes2600_op_map_tab dispatcher
- bes2600_get_cmd_and_ifname / bes2600_recyle_cmd_and_ifname_mem
string helpers
- bes2600_load_uevent + its call site in
bes2600_chrdev_wifi_force_close_work
- cdev_add / device_create / class_create in bes2600_chrdev_init +
fail label unwind
- cdev_del / device_destroy / class_destroy in bes2600_chrdev_free
- cdev/dev_id/major/minor/class/device fields in struct bes_cdev
Keeps: all in-kernel accessor functions (bes2600_chrdev_is_signal_mode
and friends), the fw_type module parameter, DPD management,
wifi_force_close kernel path (minus the userspace uevent), bus-probe
state machine.
Branch: bes2600/remove-chardev-user-interface (standalone off mobian).
Verified on PineTab2 running linux-pinetab2 6.19.10-danctnix1-1:
loaded bes2600 module is c3's (srcversion 162611C4...),
/dev/bes2600 is absent, WiFi continues to associate, bug #2 (PM
timeout) and bug #3 (SDIO TX splat) remain silenced post-reboot.
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
This commit is contained in:
+675
@@ -0,0 +1,675 @@
|
|||||||
|
From f43bcc5dda0a9120aee62cce0cec1a8c851cb4ef Mon Sep 17 00:00:00 2001
|
||||||
|
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||||
|
Date: Wed, 22 Apr 2026 12:55:18 +0200
|
||||||
|
Subject: [PATCH] bes2600: remove userspace /dev/bes2600 character device
|
||||||
|
interface
|
||||||
|
|
||||||
|
bes_chardev.c implemented a custom character device at /dev/bes2600 with
|
||||||
|
its own parser and command-dispatch table, exposing operations such as
|
||||||
|
'wifi on|off', 'bt on|off', 'change_fw_type <n>', 'bt_wakeup',
|
||||||
|
'bt_sleep', and 'wakeup_read_flag'. None of these surfaces are used by
|
||||||
|
the in-tree driver - every kernel call site consumes the internal state
|
||||||
|
accessors (bes2600_chrdev_is_signal_mode, bes2600_chrdev_get_fw_type,
|
||||||
|
etc) directly, not through the cdev.
|
||||||
|
|
||||||
|
The cdev interface is a standing upstream blocker for two reasons:
|
||||||
|
|
||||||
|
1. Drivers under drivers/staging/ and drivers/net/wireless/ are
|
||||||
|
expected to expose tuning via the firmware/nl80211/debugfs
|
||||||
|
infrastructure rather than a private /dev node with an ad-hoc
|
||||||
|
parser.
|
||||||
|
|
||||||
|
2. The cdev handlers keep a global bes_cdev singleton alive whose
|
||||||
|
->cdev, ->dev_id, ->class and ->device pointers exist only to be
|
||||||
|
torn down; they add no functionality that nl80211 or rfkill do
|
||||||
|
not already provide (wifi/bt on-off, module_param for fw_type).
|
||||||
|
|
||||||
|
Remove the userspace interface:
|
||||||
|
|
||||||
|
- open / read / write / release file_operations handlers and the
|
||||||
|
bes2600_chardev_fops instance
|
||||||
|
- bes2600_op_* command handlers and bes2600_op_map_tab dispatcher
|
||||||
|
- bes2600_get_cmd_and_ifname / bes2600_recyle_cmd_and_ifname_mem
|
||||||
|
string helpers
|
||||||
|
- bes2600_load_uevent (its only caller was
|
||||||
|
bes2600_chrdev_wifi_force_close_work informing userspace of a
|
||||||
|
state it already gates via rfkill; that snprintf +
|
||||||
|
kobject_uevent_env block is gone too, the kernel-side
|
||||||
|
halt_device + switch_wifi(0) + chrdev_check_system_close
|
||||||
|
sequence remains)
|
||||||
|
- alloc_chrdev_region / cdev_init / cdev_add / class_create /
|
||||||
|
device_create in bes2600_chrdev_init plus the fail1/fail2/fail3
|
||||||
|
unwind labels
|
||||||
|
- cdev_del / unregister_chrdev_region / device_destroy /
|
||||||
|
class_destroy in bes2600_chrdev_free
|
||||||
|
- cdev/dev_id/major/minor/class/device fields in struct bes_cdev
|
||||||
|
|
||||||
|
What remains (unchanged behaviour):
|
||||||
|
|
||||||
|
- fw_type module parameter - the primary user-facing knob for
|
||||||
|
signal/no-signal/BT mode switch
|
||||||
|
- All in-kernel bes2600_chrdev_* accessor functions called from
|
||||||
|
bes2600_sdio.c, bes_pwr.c, sta.c, bh.c, main.c, wsm.c, and
|
||||||
|
wifi_testmode_cmd.c (13 call sites)
|
||||||
|
- bes2600_chrdev_init / bes2600_chrdev_free as state-init / teardown
|
||||||
|
for the remaining bes_cdev state (waitqueues, workqueues, flags)
|
||||||
|
- DPD management (bes2600_chrdev_get_dpd_buffer / update / free)
|
||||||
|
- wifi_force_close worker, system-close logic, bus-probe state
|
||||||
|
machine
|
||||||
|
|
||||||
|
Tested-on: PineTab2 (BES2600WM + RK3566) running linux-pinetab2
|
||||||
|
6.19.10-danctnix1-1. Driver continues to associate and pass traffic;
|
||||||
|
no kernel messages related to the cdev absence. Users that previously
|
||||||
|
wrote to /dev/bes2600 should switch to the fw_type module parameter
|
||||||
|
or (future patch c4) nl80211 testmode commands.
|
||||||
|
|
||||||
|
Follow-ups:
|
||||||
|
|
||||||
|
- c3.1: thread struct device * through bes2600_chrdev_is_signal_mode
|
||||||
|
and friends so the global bes2600_cdev singleton can be dropped
|
||||||
|
and the accessors scale to multi-device scenarios.
|
||||||
|
- c4: enable CONFIG_BES2600_TESTMODE and route nl80211 testmode
|
||||||
|
commands to the firmware's patch_wifi_testMode entry.
|
||||||
|
|
||||||
|
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||||
|
---
|
||||||
|
bes2600/bes_chardev.c | 519 ------------------------------------------
|
||||||
|
1 file changed, 519 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/bes2600/bes_chardev.c b/bes2600/bes_chardev.c
|
||||||
|
index 9038e48..e2e4f1b 100644
|
||||||
|
--- a/bes2600/bes_chardev.c
|
||||||
|
+++ b/bes2600/bes_chardev.c
|
||||||
|
@@ -43,12 +43,6 @@ enum bus_probe_state {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bes_cdev {
|
||||||
|
- struct cdev cdev;
|
||||||
|
- dev_t dev_id;
|
||||||
|
- int major;
|
||||||
|
- int minor;
|
||||||
|
- struct class *class;
|
||||||
|
- struct device *device;
|
||||||
|
atomic_t num_proc;
|
||||||
|
wait_queue_head_t open_wq;
|
||||||
|
spinlock_t status_lock;
|
||||||
|
@@ -249,351 +243,18 @@ int bes2600_switch_bt(bool on)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int bes2600_get_cmd_and_ifname(const char *str, char **result)
|
||||||
|
-{
|
||||||
|
- int cmd_len = 0;
|
||||||
|
- int ifname_len = 0;
|
||||||
|
- char *sp = NULL;
|
||||||
|
- char *tmp_ptr = NULL;
|
||||||
|
- char *cmd_ptr = NULL;
|
||||||
|
-
|
||||||
|
- /* check if input arguments is valid */
|
||||||
|
- if (!str || strncmp(str, "ifname:", 7) != 0)
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- sp = strchr(str, ' ');
|
||||||
|
- if (strncmp(sp + 1, "cmd:", 4) != 0)
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- /* extract interface name */
|
||||||
|
- ifname_len = sp - str - 7;
|
||||||
|
- tmp_ptr = kmalloc(ifname_len + 1, GFP_KERNEL);
|
||||||
|
- if (!tmp_ptr) {
|
||||||
|
- return -2;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- strncpy(tmp_ptr, str+7, ifname_len);
|
||||||
|
- tmp_ptr[ifname_len] = '\0';
|
||||||
|
- result[0] = tmp_ptr;
|
||||||
|
-
|
||||||
|
- /* get command length */
|
||||||
|
- cmd_ptr = strstr(str, "cmd:");
|
||||||
|
- cmd_ptr += 4;
|
||||||
|
- sp = strchr(cmd_ptr, ' ');
|
||||||
|
- if (!sp) { /* the command don't have any parameter */
|
||||||
|
- cmd_len = strlen(cmd_ptr);
|
||||||
|
- if (cmd_ptr[cmd_len - 1] == '\n')
|
||||||
|
- --cmd_len;
|
||||||
|
- } else { /* the command have one or more parameter */
|
||||||
|
- cmd_len = sp - cmd_ptr;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* copy command to out buffer */
|
||||||
|
- tmp_ptr = kmalloc( cmd_len + 1, GFP_KERNEL);
|
||||||
|
- if (!tmp_ptr) {
|
||||||
|
- kfree(result[0]);
|
||||||
|
- result[0] = NULL;
|
||||||
|
- return -3;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- strncpy(tmp_ptr, cmd_ptr, cmd_len);
|
||||||
|
- tmp_ptr[cmd_len] = '\0';
|
||||||
|
- result[1] = tmp_ptr;
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void bes2600_recyle_cmd_and_ifname_mem(char **info)
|
||||||
|
-{
|
||||||
|
- if (info[0]) {
|
||||||
|
- kfree(info[0]);
|
||||||
|
- info[0] = NULL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (info[1]) {
|
||||||
|
- kfree(info[1]);
|
||||||
|
- info[1] = NULL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int bes2600_op_default_handler(const char *str)
|
||||||
|
-{
|
||||||
|
- char *info[2] = {0};
|
||||||
|
-
|
||||||
|
- if (bes2600_get_cmd_and_ifname(str, info) == 0) {
|
||||||
|
- bes_devel("cmd(%s) on %s not handled\n", info[1], info[0]);
|
||||||
|
- } else {
|
||||||
|
- bes_err("%s get command fail, the origin string is %s\n", __func__, str);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bes2600_recyle_cmd_and_ifname_mem(info);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int bes2600_op_wifi_bt_on_off(const char *str)
|
||||||
|
-{
|
||||||
|
- char *info[2] = {0};
|
||||||
|
- int ret = 0;
|
||||||
|
- enum wait_state wait_state;
|
||||||
|
- enum bus_probe_state probe_state;
|
||||||
|
- unsigned long status = 0;
|
||||||
|
-
|
||||||
|
- spin_lock(&bes2600_cdev.status_lock);
|
||||||
|
- probe_state = bes2600_cdev.bus_probe;
|
||||||
|
- wait_state = bes2600_cdev.wait_state;
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
-
|
||||||
|
- /* only work for wifi signal mode */
|
||||||
|
- if (bes2600_cdev.fw_type != BES2600_FW_TYPE_WIFI_SIGNAL)
|
||||||
|
- return -EFAULT;
|
||||||
|
-
|
||||||
|
- /* wait bus probe operation end */
|
||||||
|
- if (probe_state == BES2600_BUS_PROBE_START) {
|
||||||
|
- bes_devel("wait bus probe operation end\n");
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||||
|
- (bes2600_cdev.bus_probe > BES2600_BUS_PROBE_START),
|
||||||
|
- HZ);
|
||||||
|
- WARN_ON(status <= 0);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* must wait previous operation end in critical section */
|
||||||
|
- if (wait_state != BES2600_BOOT_WAIT_NONE) {
|
||||||
|
- bes_devel("wait previous operation end\n");
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||||
|
- (bes2600_cdev.wait_state == BES2600_BOOT_WAIT_NONE),
|
||||||
|
- HZ * 8);
|
||||||
|
- WARN_ON(status <= 0);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* if dpd calibration is doing, modify wifi and bt state directly */
|
||||||
|
- spin_lock(&bes2600_cdev.status_lock);
|
||||||
|
- if (bes2600_cdev.bus_probe == BES2600_BUS_PROBE_OK && !bes2600_cdev.dpd_calied) {
|
||||||
|
- if (bes2600_get_cmd_and_ifname(str, info) == 0) {
|
||||||
|
- if (strncmp(info[1], "WIFI_ON", 7) == 0) {
|
||||||
|
- bes2600_cdev.wifi_opened = true;
|
||||||
|
- } else if (strncmp(info[1], "WIFI_OFF", 8) == 0) {
|
||||||
|
- bes2600_cdev.wifi_opened = false;
|
||||||
|
- } else if (strncmp(info[1], "BT_ON", 5) == 0) {
|
||||||
|
- bes2600_cdev.bt_opened = true;
|
||||||
|
- bes2600_cdev.bton_pending = true;
|
||||||
|
- } else if (strncmp(info[1], "BT_OFF", 6) == 0) {
|
||||||
|
- bes2600_cdev.bt_opened = false;
|
||||||
|
- bes2600_cdev.bton_pending = false;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- bes2600_recyle_cmd_and_ifname_mem(info);
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
-
|
||||||
|
- /* wait probe done event */
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||||
|
- bes2600_bootup_end(), HZ * 8);
|
||||||
|
- WARN_ON(status <= 0);
|
||||||
|
-
|
||||||
|
- return (status <= 0 || bes2600_chrdev_is_bus_error()) ? -EFAULT : 0;
|
||||||
|
- }
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
-
|
||||||
|
- /* process wifi/bt on/off operation */
|
||||||
|
- if (bes2600_get_cmd_and_ifname(str, info) == 0) {
|
||||||
|
- if (strncmp(info[1], "WIFI_ON", 7) == 0) {
|
||||||
|
- ret = bes2600_switch_wifi(1);
|
||||||
|
- } else if (strncmp(info[1], "WIFI_OFF", 8) == 0) {
|
||||||
|
- ret = bes2600_switch_wifi(0);
|
||||||
|
- } else if (strncmp(info[1], "BT_ON", 5) == 0) {
|
||||||
|
- ret = bes2600_switch_bt(1);
|
||||||
|
- } else if (strncmp(info[1], "BT_OFF", 6) == 0) {
|
||||||
|
- ret = bes2600_switch_bt(0);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (!ret && bes2600_chrdev_check_system_close())
|
||||||
|
- ret = bes2600_chrdev_do_system_close(bes2600_cdev.sbus_ops,
|
||||||
|
- bes2600_cdev.sbus_priv);
|
||||||
|
-
|
||||||
|
- bes2600_recyle_cmd_and_ifname_mem(info);
|
||||||
|
-
|
||||||
|
- return ret ;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static int bes2600_op_change_fw_type(const char *str)
|
||||||
|
-{
|
||||||
|
- int ret = 0;
|
||||||
|
- int temp = 0;
|
||||||
|
- long status = 0;
|
||||||
|
- char *cmd_ptr = NULL;
|
||||||
|
- char fw_type[5] = {0};
|
||||||
|
- bool sys_closed = bes2600_chrdev_check_system_close();
|
||||||
|
-
|
||||||
|
- bes_devel("%s is called, arg:%s\n", __func__, str);
|
||||||
|
-
|
||||||
|
- if (!bes2600_cdev.sbus_ops->power_switch && !bes2600_cdev.sbus_ops->reboot)
|
||||||
|
- return -EPERM;
|
||||||
|
-
|
||||||
|
- /* check if user input is valid */
|
||||||
|
- cmd_ptr = strstr(str, "CHANGE_FW_TYPE ");
|
||||||
|
- if (strlen(str) < 16 || !cmd_ptr) {
|
||||||
|
- bes_err("the format of \"%s\" is error\n", str);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* convert fw_type from string to int */
|
||||||
|
- strncpy(fw_type, cmd_ptr + 14, 4);
|
||||||
|
- fw_type[0] = '+';
|
||||||
|
- ret = kstrtoint(fw_type, 10, &temp);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- bes_err("%s parse error\n", __func__);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* no need to realod firmware if new fw_type is equal to the old */
|
||||||
|
- if (temp == bes2600_cdev.fw_type ) {
|
||||||
|
- bes_devel("fw type is equal\n");
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* close wifi net device */
|
||||||
|
- if (bes2600_cdev.sbus_priv
|
||||||
|
- && bes2600_is_net_dev_created(bes2600_cdev.sbus_priv)) {
|
||||||
|
- bes2600_unregister_net_dev(bes2600_cdev.sbus_priv);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* update firmware type */
|
||||||
|
- bes2600_cdev.fw_type = temp;
|
||||||
|
- bes2600_chrdev_update_signal_mode();
|
||||||
|
-
|
||||||
|
- if (!sys_closed) {
|
||||||
|
- /* close device to call disconnect function */
|
||||||
|
- if (bes2600_cdev.sbus_ops->power_switch)
|
||||||
|
- bes2600_cdev.sbus_ops->power_switch(bes2600_cdev.sbus_priv, 0);
|
||||||
|
- else if (bes2600_cdev.sbus_ops->reboot)
|
||||||
|
- bes2600_cdev.sbus_ops->reboot(bes2600_cdev.sbus_priv);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (bes2600_cdev.sbus_ops->reboot)
|
||||||
|
- bes2600_chrdev_start_bus_probe();
|
||||||
|
-
|
||||||
|
- /* wait disconnect event */
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.probe_done_wq, (bes2600_cdev.sbus_priv == NULL), HZ * 10);
|
||||||
|
- WARN_ON(status <= 0);
|
||||||
|
-
|
||||||
|
- if (bes2600_cdev.dpd_calied
|
||||||
|
- && bes2600_chrdev_check_system_close()) {
|
||||||
|
- bes_devel("no need to reload firmware\n");
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bes_devel("reload firmware...\n");
|
||||||
|
- /* power on device to call probe function */
|
||||||
|
- if (bes2600_cdev.sbus_ops->power_switch)
|
||||||
|
- bes2600_cdev.sbus_ops->power_switch(NULL, 1);
|
||||||
|
-
|
||||||
|
- /* wait probe done event */
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||||
|
- bes2600_bootup_end(), HZ * 10);
|
||||||
|
- WARN_ON(status <= 0);
|
||||||
|
-
|
||||||
|
- ret = (status <= 0 || bes2600_chrdev_is_bus_error()) ? -1 : 0;
|
||||||
|
|
||||||
|
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int bes2600_op_bt_wakeup(const char *str)
|
||||||
|
-{
|
||||||
|
- int ret = 0;
|
||||||
|
- unsigned long status = 0;
|
||||||
|
-
|
||||||
|
- spin_lock(&bes2600_cdev.status_lock);
|
||||||
|
- if (!bes2600_cdev.bt_opened) {
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
- return -EFAULT;
|
||||||
|
- }
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
|
||||||
|
- /* wait probe done event */
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||||
|
- bes2600_bootup_end(), HZ * 8);
|
||||||
|
- if (status <= 0 || bes2600_chrdev_is_bus_error())
|
||||||
|
- return -EFAULT;
|
||||||
|
-
|
||||||
|
- bes_devel("bes2600 wakeup bt.\n");
|
||||||
|
- ret = bes2600_chrdev_switch_subsys(GPIO_WAKE_FLAG_BT_LP_ON, SUBSYSTEM_BT_LP, true);
|
||||||
|
-
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int bes2600_op_bt_sleep(const char *str)
|
||||||
|
-{
|
||||||
|
- int ret = 0;
|
||||||
|
- unsigned long status = 0;
|
||||||
|
-
|
||||||
|
- spin_lock(&bes2600_cdev.status_lock);
|
||||||
|
- if (!bes2600_cdev.bt_opened) {
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
- return -EFAULT;
|
||||||
|
- }
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
|
||||||
|
- /* wait probe done event */
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||||
|
- bes2600_bootup_end(), HZ * 8);
|
||||||
|
- if (status <= 0 || bes2600_chrdev_is_bus_error())
|
||||||
|
- return -EFAULT;
|
||||||
|
|
||||||
|
- bes_devel("bes2600 allow bt sleep.\n");
|
||||||
|
- ret = bes2600_chrdev_switch_subsys(GPIO_WAKE_FLAG_BT_LP_OFF, SUBSYSTEM_BT_LP, false);
|
||||||
|
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
|
||||||
|
-static int bes2600_op_set_wakeup_read_flag(const char *str)
|
||||||
|
-{
|
||||||
|
- bes_devel("%s is called, arg:%s\n", __func__, str);
|
||||||
|
- spin_lock(&bes2600_cdev.status_lock);
|
||||||
|
- bes2600_cdev.read_flag = BES_CDEV_READ_WAKEUP_STATE;
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
|
||||||
|
#ifdef FW_DOWNLOAD_UART_DAEMON
|
||||||
|
-int bes2600_load_uevent(char *env[])
|
||||||
|
-{
|
||||||
|
- return kobject_uevent_env(&bes2600_cdev.device->kobj, KOBJ_CHANGE, env);
|
||||||
|
-}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-static struct bes2600_op_map bes2600_op_map_tab[] ={
|
||||||
|
- /*op op_len handler */
|
||||||
|
- {"P2P_SET_NOA", 11, bes2600_op_default_handler},
|
||||||
|
- {"P2P_SET_PS", 10, bes2600_op_default_handler},
|
||||||
|
- {"SET_AP_WPS_P2P_IE", 17, bes2600_op_default_handler},
|
||||||
|
- {"LINKSPEED", 9, bes2600_op_default_handler},
|
||||||
|
- {"RSSI", 4, bes2600_op_default_handler},
|
||||||
|
- {"GETBAND", 7, bes2600_op_default_handler},
|
||||||
|
- {"WLS_BATCHING", 12, bes2600_op_default_handler},
|
||||||
|
- {"MACADDR", 7, bes2600_op_default_handler},
|
||||||
|
- {"RXFILTER-START", 14, bes2600_op_default_handler},
|
||||||
|
- {"RXFILTER-STOP", 13, bes2600_op_default_handler},
|
||||||
|
- {"RXFILTER-ADD", 12, bes2600_op_default_handler},
|
||||||
|
- {"RXFILTER-REMOVE", 15, bes2600_op_default_handler},
|
||||||
|
- {"BTCOEXMODE", 10, bes2600_op_default_handler},
|
||||||
|
- {"BTCOEXSCAN-START", 16, bes2600_op_default_handler},
|
||||||
|
- {"BTCOEXSCAN-STOP", 15, bes2600_op_default_handler},
|
||||||
|
- {"SETSUSPENDMODE", 14, bes2600_op_default_handler},
|
||||||
|
- {"COUNTRY", 7, bes2600_op_default_handler},
|
||||||
|
- {"WIFI_ON", 7, bes2600_op_wifi_bt_on_off},
|
||||||
|
- {"WIFI_OFF", 8, bes2600_op_wifi_bt_on_off},
|
||||||
|
- {"BT_ON", 5, bes2600_op_wifi_bt_on_off},
|
||||||
|
- {"BT_OFF", 6, bes2600_op_wifi_bt_on_off},
|
||||||
|
- {"CHANGE_FW_TYPE", 14, bes2600_op_change_fw_type},
|
||||||
|
- {"BT_WAKEUP", 9, bes2600_op_bt_wakeup},
|
||||||
|
- {"BT_SLEEP", 8, bes2600_op_bt_sleep},
|
||||||
|
- {"WAKEUP_STATE", 12, bes2600_op_set_wakeup_read_flag},
|
||||||
|
-};
|
||||||
|
|
||||||
|
static int bes2600_chrdev_check_system_close_internal(void)
|
||||||
|
{
|
||||||
|
@@ -603,123 +264,10 @@ static int bes2600_chrdev_check_system_close_internal(void)
|
||||||
|
&& (bes2600_cdev.wifi_opened == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int bes2600_chrdev_open(struct inode *inode, struct file *filp)
|
||||||
|
-{
|
||||||
|
- if (atomic_read(&bes2600_cdev.num_proc) > 0) {
|
||||||
|
- wait_event_timeout(bes2600_cdev.open_wq,
|
||||||
|
- (atomic_read(&bes2600_cdev.num_proc) == 0),
|
||||||
|
- MAX_SCHEDULE_TIMEOUT);
|
||||||
|
- }
|
||||||
|
|
||||||
|
- bes_devel("bes2600 char device is opened\n");
|
||||||
|
- atomic_inc(&bes2600_cdev.num_proc);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
|
||||||
|
-static ssize_t bes2600_chrdev_read(struct file *file, char __user *user_buf,
|
||||||
|
- size_t count, loff_t *ppos)
|
||||||
|
-{
|
||||||
|
- char buf[64] = {0};
|
||||||
|
- unsigned int len;
|
||||||
|
- long status = 0;
|
||||||
|
|
||||||
|
- switch (bes2600_cdev.read_flag) {
|
||||||
|
- case BES_CDEV_READ_WAKEUP_STATE:
|
||||||
|
- if (bes2600_chrdev_wakeup_by_event_get() > WAKEUP_EVENT_NONE) {
|
||||||
|
- status = wait_event_timeout(bes2600_cdev.wakeup_reason_wq,
|
||||||
|
- bes2600_chrdev_wakeup_by_event_get() == WAKEUP_EVENT_NONE, HZ * 2);
|
||||||
|
- WARN_ON(status <= 0);
|
||||||
|
- }
|
||||||
|
- len = sprintf(buf, "wakeup_reason: %u, src_port: %u\n",
|
||||||
|
- bes2600_cdev.wakeup_state, bes2600_cdev.src_port);
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- len = sprintf(buf, "dpd_calied:%d wifi_opened:%d bt_opened:%d fw_type:%d\n",
|
||||||
|
- bes2600_cdev.dpd_calied,
|
||||||
|
- bes2600_cdev.wifi_opened,
|
||||||
|
- bes2600_cdev.bt_opened,
|
||||||
|
- bes2600_cdev.fw_type);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- len = sizeof(buf);
|
||||||
|
- /* reset read flag */
|
||||||
|
- spin_lock(&bes2600_cdev.status_lock);
|
||||||
|
- bes2600_cdev.read_flag = BES_CDEV_READ_NUM_MAX;
|
||||||
|
- spin_unlock(&bes2600_cdev.status_lock);
|
||||||
|
-
|
||||||
|
- return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static ssize_t bes2600_chrdev_write(struct file *file,
|
||||||
|
- const char __user *user_buf, size_t count, loff_t *ppos)
|
||||||
|
-{
|
||||||
|
- int i = 0;
|
||||||
|
- int cmd_num = ARRAY_SIZE(bes2600_op_map_tab);
|
||||||
|
- int cmd_len = 0;
|
||||||
|
- int ret = 0;
|
||||||
|
- char *info[2] = {0};
|
||||||
|
- char *buf = NULL;
|
||||||
|
-
|
||||||
|
- /* copy content from user space to kernel */
|
||||||
|
- /* message format:"ifname:wlanx cmd:xxx arg1 arg2 ..." */
|
||||||
|
- buf = kmalloc(count + 1, GFP_KERNEL);
|
||||||
|
- if (copy_from_user(buf, user_buf, count))
|
||||||
|
- return -EFAULT;
|
||||||
|
-
|
||||||
|
- /* add terminal character */
|
||||||
|
- buf[count] = '\0';
|
||||||
|
-
|
||||||
|
- /* extract comand and interface */
|
||||||
|
- if (bes2600_get_cmd_and_ifname(buf, info) != 0) {
|
||||||
|
- bes_err("%s get command fail, the origin string is %s\n", __func__, buf);
|
||||||
|
- kfree(buf);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* match operation item and execure its handler */
|
||||||
|
- cmd_len = strlen(info[1]);
|
||||||
|
- for (i = 0; i < cmd_num; i++) {
|
||||||
|
- if (cmd_len < bes2600_op_map_tab[i].op_len)
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
- if (strncasecmp(info[1], bes2600_op_map_tab[i].op, bes2600_op_map_tab[i].op_len) == 0) {
|
||||||
|
- ret = bes2600_op_map_tab[i].handler(buf);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* operation item mismatch */
|
||||||
|
- if (i == cmd_num) {
|
||||||
|
- bes_err("cmd(%s) mismatch\n", info[1]);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bes2600_recyle_cmd_and_ifname_mem(info);
|
||||||
|
- kfree(buf);
|
||||||
|
-
|
||||||
|
- return (ret == 0) ? count : ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int bes2600_chrdev_release (struct inode *inode, struct file *file)
|
||||||
|
-{
|
||||||
|
- if (atomic_dec_and_test(&bes2600_cdev.num_proc)) {
|
||||||
|
- wake_up(&bes2600_cdev.open_wq);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bes_devel("bes2600 char device is closed\n");
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static struct file_operations bes2600_chardev_fops =
|
||||||
|
-{
|
||||||
|
- .owner = THIS_MODULE,
|
||||||
|
- .open = bes2600_chrdev_open,
|
||||||
|
- .read = bes2600_chrdev_read,
|
||||||
|
- .write = bes2600_chrdev_write,
|
||||||
|
- .release = bes2600_chrdev_release,
|
||||||
|
-};
|
||||||
|
|
||||||
|
#ifdef BES2600_WRITE_DPD_TO_FILE
|
||||||
|
static int bes2600_chrdev_write_dpd_data_to_file(const char *path, void *buffer, int size)
|
||||||
|
@@ -1124,12 +672,6 @@ void bes2600_chrdev_update_signal_mode(void)
|
||||||
|
|
||||||
|
static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
- char wifi_state[15];
|
||||||
|
- char bt_state[15];
|
||||||
|
- char fw_type[15];
|
||||||
|
- char *env[] = { wifi_state, bt_state, fw_type, NULL };
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
if (bes2600_chrdev_is_wifi_opened()) {
|
||||||
|
bes_devel("system exeception, force wifi down\n");
|
||||||
|
|
||||||
|
@@ -1146,14 +688,6 @@ static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
|
||||||
|
bes2600_chrdev_do_system_close(bes2600_cdev.sbus_ops,
|
||||||
|
bes2600_cdev.sbus_priv);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- /* notify userspace */
|
||||||
|
- snprintf(wifi_state, sizeof(wifi_state), "WIFI_OPENED=%d", bes2600_cdev.wifi_opened);
|
||||||
|
- snprintf(bt_state, sizeof(bt_state), "BT_OPENED=%d", bes2600_cdev.bt_opened);
|
||||||
|
- snprintf(fw_type, sizeof(fw_type), "FW_TYPE=%d", bes2600_cdev.fw_type);
|
||||||
|
- ret = kobject_uevent_env(&bes2600_cdev.device->kobj, KOBJ_CHANGE, env);
|
||||||
|
- if (!ret)
|
||||||
|
- bes_err("bes2600 notify userspace failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1247,46 +781,6 @@ int bes2600_chrdev_wakeup_by_event_get(void)
|
||||||
|
|
||||||
|
int bes2600_chrdev_init(struct sbus_ops *ops)
|
||||||
|
{
|
||||||
|
- int ret = 0;
|
||||||
|
-
|
||||||
|
- /* allocate devide id */
|
||||||
|
- ret = alloc_chrdev_region(&bes2600_cdev.dev_id, 0, 1, "bes2600_chrdev");
|
||||||
|
- if (ret < 0){
|
||||||
|
- bes_err("bes2600 alloc device id fail\n");
|
||||||
|
- ret = -EFAULT;
|
||||||
|
- goto fail;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* extract major and minor device id */
|
||||||
|
- bes2600_cdev.major = MAJOR(bes2600_cdev.dev_id);
|
||||||
|
- bes2600_cdev.minor = MINOR(bes2600_cdev.dev_id);
|
||||||
|
-
|
||||||
|
- /* add char device and bind operation function */
|
||||||
|
- bes2600_cdev.cdev.owner = THIS_MODULE;
|
||||||
|
- cdev_init(&bes2600_cdev.cdev, &bes2600_chardev_fops);
|
||||||
|
- ret = cdev_add(&bes2600_cdev.cdev, bes2600_cdev.dev_id, 1);
|
||||||
|
- if (ret < 0){
|
||||||
|
- bes_err("bes2600 char device add fail\n");
|
||||||
|
- ret = -EFAULT;
|
||||||
|
- goto fail1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* create class for creating device node */
|
||||||
|
- bes2600_cdev.class = class_create("bes2600_chrdev");
|
||||||
|
- if (IS_ERR(bes2600_cdev.class)){
|
||||||
|
- bes_err("bes2600 char device add fail\n");
|
||||||
|
- ret = -EFAULT;
|
||||||
|
- goto fail2;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* get char device pointer */
|
||||||
|
- bes2600_cdev.device = device_create(bes2600_cdev.class, NULL, bes2600_cdev.dev_id, NULL, "bes2600");
|
||||||
|
- if (IS_ERR(bes2600_cdev.device)){
|
||||||
|
- bes_err("bes2600 char device create fail\n");
|
||||||
|
- ret = -EFAULT;
|
||||||
|
- goto fail3;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
/* initialise global variable */
|
||||||
|
atomic_set(&bes2600_cdev.num_proc, 0);
|
||||||
|
init_waitqueue_head(&bes2600_cdev.open_wq);
|
||||||
|
@@ -1318,15 +812,6 @@ int bes2600_chrdev_init(struct sbus_ops *ops)
|
||||||
|
bes_devel("%s done\n", __func__);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
-
|
||||||
|
-fail3:
|
||||||
|
- class_destroy(bes2600_cdev.class);
|
||||||
|
-fail2:
|
||||||
|
- cdev_del(&bes2600_cdev.cdev);
|
||||||
|
-fail1:
|
||||||
|
- unregister_chrdev_region(bes2600_cdev.dev_id, 1);
|
||||||
|
-fail:
|
||||||
|
- return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bes2600_chrdev_free(void)
|
||||||
|
@@ -1336,9 +821,5 @@ void bes2600_chrdev_free(void)
|
||||||
|
bes2600_free_dpd_log_buffer();
|
||||||
|
#endif
|
||||||
|
bes2600_chrdev_free_dpd_data();
|
||||||
|
- cdev_del(&bes2600_cdev.cdev);
|
||||||
|
- unregister_chrdev_region(bes2600_cdev.dev_id, 1);
|
||||||
|
- device_destroy(bes2600_cdev.class, bes2600_cdev.dev_id);
|
||||||
|
- class_destroy(bes2600_cdev.class);
|
||||||
|
bes_devel("%s done\n", __func__);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.53.0
|
||||||
|
|
||||||
Reference in New Issue
Block a user