mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
Make sure mt7921_pm_wake_work wouldn't be scheduled after the driver is in suspend mode to fix the following the kernel crash. [ 3515.390012] mt7921e 0000:01:00.0: calling pci_pm_suspend+0x0/0x22c @ 2869, parent: 0000:00:00.0 [ 3515.390015] mt7921e 0000:01:00.0: mt7921_pci_suspend + [ 3515.396395] anx7625 3-0058: anx7625_suspend+0x0/0x6c returned 0 after 0 usecs [ 3515.405965] mt7921e 0000:01:00.0: mt7921_pci_suspend - [ 3515.411336] usb 1-1.4: usb_dev_suspend+0x0/0x2c returned 0 after 1 usecs [ 3515.411513] SError Interrupt on CPU7, code 0xbe000011 -- SError [ 3515.411515] CPU: 7 PID: 2849 Comm: kworker/u16:27 Not tainted 5.4.114 #44 [ 3515.411516] Hardware name: MediaTek Asurada rev1 board (DT) [ 3515.411517] Workqueue: mt76 mt7921_pm_wake_work [mt7921e] [ 3515.411518] pstate: 80c00009 (Nzcv daif +PAN +UAO) [ 3515.411519] pc : mt76_mmio_rr+0x30/0xf0 [mt76] [ 3515.411520] lr : mt7921_rr+0x38/0x44 [mt7921e] [ 3515.411520] sp : ffffffc015813c50 [ 3515.411521] x29: ffffffc015813c50 x28: 0000000000000402 [ 3515.411522] x27: ffffffe5a2012138 x26: ffffffe5a1eea018 [ 3515.411524] x25: 00000000328be505 x24: 00000000000a0002 [ 3515.411525] x23: 0000000000000006 x22: ffffffbd29b7a300 [ 3515.411527] x21: ffffffbd29b7a300 x20: 00000000000e0010 [ 3515.411528] x19: 00000000eac08f43 x18: 0000000000000000 [ 3515.411529] x17: 0000000000000000 x16: ffffffe5a16b2914 [ 3515.411531] x15: 0000000000000010 x14: 0000000000000010 [ 3515.411532] x13: 00000000003dd3a2 x12: 0000000000010000 [ 3515.411533] x11: ffffffe597abec14 x10: 0000000000000010 [ 3515.411535] x9 : ffffffe597abeba8 x8 : ffffffc013ce0010 [ 3515.411536] x7 : 000000b2b5593519 x6 : 0000000000300000 [ 3515.411537] x5 : 0000000000000000 x4 : 0000000000000032 [ 3515.411539] x3 : 0000000000000000 x2 : 0000000000000004 [ 3515.411540] x1 : 00000000000e0010 x0 : ffffffbd29b7a300 [ 3515.411542] Kernel panic - not syncing: Asynchronous SError Interrupt [ 3515.411543] CPU: 7 PID: 2849 Comm: kworker/u16:27 Not tainted 5.4.114 #44 [ 3515.411544] Hardware name: MediaTek Asurada rev1 board (DT) [ 3515.411544] Workqueue: mt76 mt7921_pm_wake_work [mt7921e] [ 3515.411545] Call trace: [ 3515.411546] dump_backtrace+0x0/0x14c [ 3515.411546] show_stack+0x20/0x2c [ 3515.411547] dump_stack+0xa0/0xfc [ 3515.411548] panic+0x154/0x350 [ 3515.411548] panic+0x0/0x350 [ 3515.411549] arm64_serror_panic+0x78/0x84 [ 3515.411550] do_serror+0x0/0x118 [ 3515.411550] do_serror+0xa4/0x118 [ 3515.411551] el1_error+0x84/0xf8 [ 3515.411552] mt76_mmio_rr+0x30/0xf0 [mt76] [ 3515.411552] mt7921_rr+0x38/0x44 [mt7921e] [ 3515.411553] __mt76_poll_msec+0x5c/0x9c [mt76] [ 3515.411554] __mt7921_mcu_drv_pmctrl+0x50/0x94 [mt7921e] [ 3515.411555] mt7921_mcu_drv_pmctrl+0x38/0xb0 [mt7921e] [ 3515.411555] mt7921_pm_wake_work+0x34/0xd4 [mt7921e] [ 3515.411556] process_one_work+0x208/0x3c8 [ 3515.411557] worker_thread+0x23c/0x3e8 [ 3515.411557] kthread+0x144/0x178 [ 3515.411558] ret_from_fork+0x10/0x18 [ 3515.418831] SMP: stopping secondary CPUs [ 3515.418832] Kernel Offset: 0x2590c00000 from 0xffffffc010000000 [ 3515.418832] PHYS_OFFSET: 0xffffffc400000000 [ 3515.418833] CPU features: 0x080026,2a80aa18 [ 3515.418834] Memory Limit: none [DL] 00000000 00000000 010701 Fixes: 1d8efc741df80 ("mt76: mt7921: introduce Runtime PM support") Co-developed-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Sean Wang <[email protected]> Signed-off-by: Felix Fietkau <[email protected]>
174 lines
3.6 KiB
C
174 lines
3.6 KiB
C
/* SPDX-License-Identifier: ISC */
|
|
/* Copyright (C) 2020 MediaTek Inc. */
|
|
|
|
#ifndef __MT76_CONNAC_H
|
|
#define __MT76_CONNAC_H
|
|
|
|
#include "mt76.h"
|
|
|
|
#define MT76_CONNAC_SCAN_IE_LEN 600
|
|
#define MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL 10
|
|
#define MT76_CONNAC_MAX_SCHED_SCAN_SSID 10
|
|
#define MT76_CONNAC_MAX_SCAN_MATCH 16
|
|
|
|
#define MT76_CONNAC_COREDUMP_TIMEOUT (HZ / 20)
|
|
#define MT76_CONNAC_COREDUMP_SZ (128 * 1024)
|
|
|
|
enum {
|
|
CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20,
|
|
CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40,
|
|
CMD_CBW_80MHZ = IEEE80211_STA_RX_BW_80,
|
|
CMD_CBW_160MHZ = IEEE80211_STA_RX_BW_160,
|
|
CMD_CBW_10MHZ,
|
|
CMD_CBW_5MHZ,
|
|
CMD_CBW_8080MHZ,
|
|
|
|
CMD_HE_MCS_BW80 = 0,
|
|
CMD_HE_MCS_BW160,
|
|
CMD_HE_MCS_BW8080,
|
|
CMD_HE_MCS_BW_NUM
|
|
};
|
|
|
|
enum {
|
|
HW_BSSID_0 = 0x0,
|
|
HW_BSSID_1,
|
|
HW_BSSID_2,
|
|
HW_BSSID_3,
|
|
HW_BSSID_MAX = HW_BSSID_3,
|
|
EXT_BSSID_START = 0x10,
|
|
EXT_BSSID_1,
|
|
EXT_BSSID_15 = 0x1f,
|
|
EXT_BSSID_MAX = EXT_BSSID_15,
|
|
REPEATER_BSSID_START = 0x20,
|
|
REPEATER_BSSID_MAX = 0x3f,
|
|
};
|
|
|
|
struct mt76_connac_pm {
|
|
bool enable;
|
|
bool suspended;
|
|
|
|
spinlock_t txq_lock;
|
|
struct {
|
|
struct mt76_wcid *wcid;
|
|
struct sk_buff *skb;
|
|
} tx_q[IEEE80211_NUM_ACS];
|
|
|
|
struct work_struct wake_work;
|
|
wait_queue_head_t wait;
|
|
|
|
struct {
|
|
spinlock_t lock;
|
|
u32 count;
|
|
} wake;
|
|
struct mutex mutex;
|
|
|
|
struct delayed_work ps_work;
|
|
unsigned long last_activity;
|
|
unsigned long idle_timeout;
|
|
|
|
struct {
|
|
unsigned long last_wake_event;
|
|
unsigned long awake_time;
|
|
unsigned long last_doze_event;
|
|
unsigned long doze_time;
|
|
unsigned int lp_wake;
|
|
} stats;
|
|
};
|
|
|
|
struct mt76_connac_coredump {
|
|
struct sk_buff_head msg_list;
|
|
struct delayed_work work;
|
|
unsigned long last_activity;
|
|
};
|
|
|
|
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
|
|
|
|
static inline bool is_mt7921(struct mt76_dev *dev)
|
|
{
|
|
return mt76_chip(dev) == 0x7961;
|
|
}
|
|
|
|
static inline bool is_mt7663(struct mt76_dev *dev)
|
|
{
|
|
return mt76_chip(dev) == 0x7663;
|
|
}
|
|
|
|
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
|
|
void mt76_connac_power_save_sched(struct mt76_phy *phy,
|
|
struct mt76_connac_pm *pm);
|
|
void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
|
|
struct mt76_wcid *wcid);
|
|
|
|
static inline bool
|
|
mt76_connac_pm_ref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
|
|
{
|
|
bool ret = false;
|
|
|
|
if (!pm->enable)
|
|
return true;
|
|
|
|
spin_lock_bh(&pm->wake.lock);
|
|
if (test_bit(MT76_STATE_PM, &phy->state))
|
|
goto out;
|
|
|
|
pm->wake.count++;
|
|
ret = true;
|
|
out:
|
|
spin_unlock_bh(&pm->wake.lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline void
|
|
mt76_connac_pm_unref(struct mt76_connac_pm *pm)
|
|
{
|
|
if (!pm->enable)
|
|
return;
|
|
|
|
spin_lock_bh(&pm->wake.lock);
|
|
pm->wake.count--;
|
|
pm->last_activity = jiffies;
|
|
spin_unlock_bh(&pm->wake.lock);
|
|
}
|
|
|
|
static inline bool
|
|
mt76_connac_skip_fw_pmctrl(struct mt76_phy *phy, struct mt76_connac_pm *pm)
|
|
{
|
|
struct mt76_dev *dev = phy->dev;
|
|
bool ret;
|
|
|
|
if (dev->token_count)
|
|
return true;
|
|
|
|
spin_lock_bh(&pm->wake.lock);
|
|
ret = pm->wake.count || test_and_set_bit(MT76_STATE_PM, &phy->state);
|
|
spin_unlock_bh(&pm->wake.lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline void
|
|
mt76_connac_mutex_acquire(struct mt76_dev *dev, struct mt76_connac_pm *pm)
|
|
__acquires(&dev->mutex)
|
|
{
|
|
mutex_lock(&dev->mutex);
|
|
mt76_connac_pm_wake(&dev->phy, pm);
|
|
}
|
|
|
|
static inline void
|
|
mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
|
|
__releases(&dev->mutex)
|
|
{
|
|
mt76_connac_power_save_sched(&dev->phy, pm);
|
|
mutex_unlock(&dev->mutex);
|
|
}
|
|
|
|
void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
|
|
struct mt76_connac_pm *pm,
|
|
struct mt76_wcid *wcid,
|
|
struct sk_buff *skb);
|
|
void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
|
|
struct mt76_connac_pm *pm);
|
|
|
|
#endif /* __MT76_CONNAC_H */
|