// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#include <linux/relay.h>
#include "mt7996.h"
#include "eeprom.h"
#include "mcu.h"
#include "mac.h"
#define FW_BIN_LOG_MAGIC 0x44d9c99a
/** global debugfs **/
struct hw_queue_map {
const char *name;
u8 index;
u8 pid;
u8 qid;
};
static int
mt7996_implicit_txbf_set(void *data, u64 val)
{
struct mt7996_dev *dev = data;
/* The existing connected stations shall reconnect to apply
* new implicit txbf configuration.
*/
dev->ibf = !!val;
return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
}
static int
mt7996_implicit_txbf_get(void *data, u64 *val)
{
struct mt7996_dev *dev = data;
*val = dev->ibf;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7996_implicit_txbf_get,
mt7996_implicit_txbf_set, "%lld\n");
/* test knob of system error recovery */
static ssize_t
mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct mt7996_dev *dev = file->private_data;
char buf[16], *sep;
int ret = 0;
u16 band, val;
if (count >= sizeof(buf))
return -EINVAL;
if (copy_from_user(buf, user_buf, count))
return -EFAULT;
if (count && buf[count - 1] == '\n')
buf[count - 1] = '\0';
else
buf[count] = '\0';
sep = strchr(buf, ',');
if (!sep)
return -EINVAL;
*sep = 0;
if (kstrtou16(buf, 0, &band) || kstrtou16(sep + 1, 0, &val))
return -EINVAL;
switch (val) {
/*
* <band>,0: grab firmware current SER state.
* <band>,1: trigger & enable system error L1 recovery.
* <band>,2: trigger & enable system error L2 recovery.
* <band>,3: trigger & enable system error L3 rx abort.
* <band>,4: trigger & enable system error L3 tx abort
* <band>,5: trigger & enable system error L3 tx disable.
* <band>,6: trigger & enable system error L3 bf recovery.
* <band>,7: trigger & enable system error L4 mdp recovery.
* <band>,8: trigger & enable system error full recovery.
* <band>,9: trigger firmware crash.
*/
case UNI_CMD_SER_QUERY:
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band);
break;
case UNI_CMD_SER_SET_RECOVER_L1:
case UNI_CMD_SER_SET_RECOVER_L2:
case UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT:
case UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT:
case UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE:
case UNI_CMD_SER_SET_RECOVER_L3_BF:
case UNI_CMD_SER_SET_RECOVER_L4_MDP:
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_SET, BIT(val), band);
if (ret)
return ret;
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, val, band);
break;
/* enable full chip reset */
case UNI_CMD_SER_SET_RECOVER_FULL:
mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
mt7996_reset(dev);
break;
/* WARNING: trigger firmware crash */
case UNI_CMD_SER_SET_SYSTEM_ASSERT:
ret = mt7996_mcu_trigger_assert(dev);
if (ret)
return ret;
break;
default:
break;
}
return ret ? ret : count;
}
static ssize_t
mt7996_sys_recovery_get(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct mt7996_dev *dev = file->private_data;
char *buff;
int desc =