Skip to content

wifi: ath9k: Add PTP patch from wifi-ptp project #6882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: rpi-6.12.y
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath9k/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ath9k-y += beacon.o \
channel.o

ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o ptp.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
Expand Down
33 changes: 29 additions & 4 deletions drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@
#include <linux/leds.h>
#include <linux/completion.h>
#include <linux/time.h>
#include <linux/ktime.h>
#include <linux/timecounter.h>
#include <linux/hw_random.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/ptp_classify.h>
#include <linux/hrtimer.h>

#include "common.h"
#include "debug.h"
Expand Down Expand Up @@ -109,7 +114,7 @@
/* minimum h/w qdepth to be sustained to maximize aggregation */
#define ATH_AGGR_MIN_QDEPTH 2
/* minimum h/w qdepth for non-aggregated traffic */
#define ATH_NON_AGGR_MIN_QDEPTH 8
#define ATH_NON_AGGR_MIN_QDEPTH 32
#define ATH_HW_CHECK_POLL_INT 1000
#define ATH_TXFIFO_DEPTH 8
#define ATH_TX_ERROR 0x01
Expand Down Expand Up @@ -579,7 +584,7 @@
u32 ath_calcrxfilter(struct ath_softc *sc);
int ath_rx_init(struct ath_softc *sc, int nbufs);
void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp, ktime_t *tstamp);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
Expand All @@ -601,7 +606,7 @@
void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct sk_buff *skb);
void ath_tx_tasklet(struct ath_softc *sc);
void ath_tx_edma_tasklet(struct ath_softc *sc);
void ath_tx_edma_tasklet(struct ath_softc *sc, ktime_t *tstamp);
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn);
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
Expand Down Expand Up @@ -1018,12 +1023,27 @@

u8 gtt_cnt;
u32 intrstatus;
u16 ps_flags; /* PS_* */
ktime_t intrtstamp;
u16 ps_flags; /* PS_* */

Check failure on line 1027 in drivers/net/wireless/ath/ath9k/ath9k.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line

Check failure on line 1027 in drivers/net/wireless/ath/ath9k/ath9k.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no space before tabs

Check failure on line 1027 in drivers/net/wireless/ath/ath9k/ath9k.h

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: code indent should use tabs where possible
bool ps_enabled;
bool ps_idle;
short nbcnvifs;
unsigned long ps_usecount;

spinlock_t systim_lock;
struct cyclecounter cc;
struct timecounter tc;
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info;
u32 cc_mult;
struct hrtimer off_timer;
ktime_t off_interval;
u32 off_counter;
s64 off_last;
u64 off_base_time;

u64 ptp_dirtyts;

struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
Expand Down Expand Up @@ -1152,4 +1172,9 @@
static inline void ath_ahb_exit(void) {};
#endif

void ath9k_ptp_init(struct ath_softc *sc);
void ath9k_ptp_remove(struct ath_softc *sc);
void ath9k_cyc2hwtstamp(struct ath_softc *sc, struct skb_shared_hwtstamps *hwtstamps, u32 cycle);
#define ATH9K_PTP_FAKE_SHIFT 21

#endif /* ATH9K_H */
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath9k/beacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc)

if (sc->sc_ah->opmode != NL80211_IFTYPE_AP &&
sc->sc_ah->opmode != NL80211_IFTYPE_MESH_POINT) {
ath_dbg(common, BEACON, "slot 0, tsf: %llu\n",
ath9k_hw_gettsf64(sc->sc_ah));
// ath_dbg(common, BEACON, "slot 0, tsf: %llu\n",
// ath9k_hw_gettsf64(sc->sc_ah));
return 0;
}

Expand Down
91 changes: 91 additions & 0 deletions drivers/net/wireless/ath/ath9k/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,91 @@

#endif

static ssize_t read_file_dirtyts(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) {

Check failure on line 124 in drivers/net/wireless/ath/ath9k/debug.c

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: open brace '{' following function definitions go on the next line

Check failure on line 124 in drivers/net/wireless/ath/ath9k/debug.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 104 exceeds 100 columns
struct ath_softc *sc = file->private_data;

Check failure on line 125 in drivers/net/wireless/ath/ath9k/debug.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line
u8 buf[sizeof(u64)];

Check failure on line 126 in drivers/net/wireless/ath/ath9k/debug.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line

memcpy(buf, &sc->ptp_dirtyts, sizeof buf);

Check failure on line 128 in drivers/net/wireless/ath/ath9k/debug.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: sizeof buf should be sizeof(buf)

Check failure on line 128 in drivers/net/wireless/ath/ath9k/debug.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line
return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof buf);

Check failure on line 129 in drivers/net/wireless/ath/ath9k/debug.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line
}

static ssize_t write_file_dirtyts(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos) {
struct ath_softc *sc = file->private_data;
u8 buf[sizeof(u64)];
ssize_t len;
u64 dirty_cycle;
u32 raw_tsf;
s64 delta;
s64 dirty_ns;
unsigned long flags;
u32 remain;

len = simple_write_to_buffer(buf, sizeof buf, ppos, user_buf, count);
if (len < 0) {
return len;
}
if (len < sizeof buf) {
return -EINVAL;
}

memcpy(&dirty_cycle, buf, sizeof buf);
raw_tsf = (dirty_cycle >> 32);
remain = dirty_cycle & 0xffffffffU;

spin_lock_irqsave(&sc->systim_lock, flags);
dirty_ns = timecounter_cyc2time(&sc->tc, raw_tsf);
delta = 0;
if (remain) {
u64 frac = 0;
delta = cyclecounter_cyc2ns(&sc->cc, 1, sc->cc.mask, &frac);
delta = delta * remain / 1000;
}
spin_unlock_irqrestore(&sc->systim_lock, flags);

dirty_ns += delta;
sc->ptp_dirtyts = dirty_ns;

return len;
}

static const struct file_operations fops_dirtyts = {
.read = read_file_dirtyts,
.write = write_file_dirtyts,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};

static ssize_t read_file_trigger_cbr(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) {
return -EINVAL;
}

static ssize_t write_file_trigger_cbr(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos) {
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;

if (count & 1) {
printk("ath9k: cbr open\n");
// REG_RMW(ah, AR_QMISC(ATH_TXQ_AC_VI), AR_Q_MISC_FSP_CBR, AR_Q_MISC_FSP);
REG_WRITE(ah, AR_QCBRCFG(ATH_TXQ_AC_VI), 0xc350);
} else {
printk("ath9k: cbr gated\n");
// REG_RMW(ah, AR_QMISC(ATH_TXQ_AC_VI), 0x4, AR_Q_MISC_FSP);
}

return count;
}

static const struct file_operations fops_trigger_cbr = {
.read = read_file_trigger_cbr,
.write = write_file_trigger_cbr,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};

#define DMA_BUF_LEN 1024


Expand Down Expand Up @@ -1427,6 +1512,12 @@
sc->debug.debugfs_phy,
read_file_dump_nfcal);

debugfs_create_file("dirtyts", 0600, sc->debug.debugfs_phy,
sc, &fops_dirtyts);

debugfs_create_file("trigger_cbr", 0600, sc->debug.debugfs_phy,
sc, &fops_trigger_cbr);

ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah);

Expand Down
5 changes: 3 additions & 2 deletions drivers/net/wireless/ath/ath9k/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3035,8 +3035,8 @@ EXPORT_SYMBOL(ath9k_hw_gettsf64);

void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64)
{
REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
// REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
// REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
}
EXPORT_SYMBOL(ath9k_hw_settsf64);

Expand All @@ -3056,6 +3056,7 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set)
if (set)
ah->misc_mode |= AR_PCU_TX_ADD_TSF;
else
// ;
ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
}
EXPORT_SYMBOL(ath9k_hw_set_tsfadjust);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath9k/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@
enum ath_hw_txq_subtype {
ATH_TXQ_AC_BK = 0,
ATH_TXQ_AC_BE = 1,
ATH_TXQ_AC_VI = 2,
ATH_TXQ_AC_VI = 5,
ATH_TXQ_AC_VO = 3,
};

Expand Down
10 changes: 9 additions & 1 deletion drivers/net/wireless/ath/ath9k/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,16 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
spin_lock_irqsave(&sc->sc_serial_rw, flags);
val = ioread32(sc->mem + reg_offset);
spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
} else
} else {
/*
if (reg_offset == AR_TSF_L32) {
printk("ath9k: ioread32 unlock L32");
} else if (reg_offset == AR_TSF_U32) {
printk("ath9k: ioread32 unlock U32");
}
*/
val = ioread32(sc->mem + reg_offset);
}
return val;
}

Expand Down
14 changes: 14 additions & 0 deletions drivers/net/wireless/ath/ath9k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_tx_queue_info *qi;
u32 cwMin, chanCwMin, value;
int hcfenabled = 0;

qi = &ah->txq[q];
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
Expand All @@ -378,6 +379,14 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)

ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q);

if (q == ATH_TXQ_AC_VI) {
qi->tqi_cwmin = qi->tqi_cwmax = 0;
qi->tqi_aifs = 0;
qi->tqi_cbrPeriod = 5000;
qi->tqi_cbrOverflowLimit = 0;
// hcfenabled = 1;
}

if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
chanCwMin = INIT_CWMIN;

Expand Down Expand Up @@ -413,8 +422,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |
(qi->tqi_cbrOverflowLimit ?
AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
// REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_ONE_SHOT_EN);
}
if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
printk("ath9k: tqi set rdytime: %d\n", q);
REG_WRITE(ah, AR_QRDYTIMECFG(q),
SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
AR_Q_RDYTIMECFG_EN);
Expand Down Expand Up @@ -494,6 +505,9 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
break;
}

if (hcfenabled) {
REG_SET_BIT(ah, AR_QMISC(q), 0x00000016);
}
if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
REG_SET_BIT(ah, AR_DMISC(q),
SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
Expand Down
30 changes: 26 additions & 4 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <linux/nl80211.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include "ath9k.h"
#include "btcoex.h"

Expand Down Expand Up @@ -384,10 +385,12 @@ void ath9k_tasklet(struct tasklet_struct *t)
unsigned long flags;
u32 status;
u32 rxmask;
ktime_t tstamp;

spin_lock_irqsave(&sc->intr_lock, flags);
status = sc->intrstatus;
sc->intrstatus = 0;
tstamp = sc->intrtstamp;
spin_unlock_irqrestore(&sc->intr_lock, flags);

ath9k_ps_wakeup(sc);
Expand Down Expand Up @@ -436,7 +439,7 @@ void ath9k_tasklet(struct tasklet_struct *t)
* the next Beacon.
*/
ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n");
sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
// sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
}
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);

Expand All @@ -450,9 +453,9 @@ void ath9k_tasklet(struct tasklet_struct *t)
/* Check for high priority Rx first */
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_RXHP))
ath_rx_tasklet(sc, 0, true);
ath_rx_tasklet(sc, 0, true, &tstamp);

ath_rx_tasklet(sc, 0, false);
ath_rx_tasklet(sc, 0, false, &tstamp);
}

if (status & ATH9K_INT_TX) {
Expand All @@ -465,7 +468,7 @@ void ath9k_tasklet(struct tasklet_struct *t)
*/
sc->gtt_cnt = 0;

ath_tx_edma_tasklet(sc);
ath_tx_edma_tasklet(sc, &tstamp);
} else {
ath_tx_tasklet(sc);
}
Expand Down Expand Up @@ -509,6 +512,9 @@ irqreturn_t ath_isr(int irq, void *dev)
enum ath9k_int status;
u32 sync_cause = 0;
bool sched = false;
ktime_t isr_tstamp = ktime_get_real();

//printk("ath9k: ath_isr isr_tstamp=%lld, tsf64=%u\n", isr_tstamp, ath9k_hw_gettsf32(ah));

/*
* The hardware is not ready/present, don't
Expand Down Expand Up @@ -547,6 +553,7 @@ irqreturn_t ath_isr(int irq, void *dev)
/* Cache the status */
spin_lock(&sc->intr_lock);
sc->intrstatus |= status;
sc->intrtstamp = isr_tstamp;
spin_unlock(&sc->intr_lock);

if (status & SCHED_INTR)
Expand Down Expand Up @@ -760,6 +767,8 @@ static void ath9k_tx(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
unsigned long flags;

ath_warn(common, "ath9k_tx skb=%p, skb->sk=%p\n", skb, skb->sk);

if (sc->ps_enabled) {
/*
* mac80211 does not set PM field for normal data frames, so we
Expand Down Expand Up @@ -2837,3 +2846,16 @@ struct ieee80211_ops ath9k_ops = {
.get_txpower = ath9k_get_txpower,
.wake_tx_queue = ath9k_wake_tx_queue,
};

void ath9k_cyc2hwtstamp(struct ath_softc *sc, struct skb_shared_hwtstamps *hwtstamps, u32 cycle) {
u64 ns;
unsigned long flags;

spin_lock_irqsave(&sc->systim_lock, flags);
ns = timecounter_cyc2time(&sc->tc, (u64)cycle);
spin_unlock_irqrestore(&sc->systim_lock, flags);

memset(hwtstamps, 0, sizeof(*hwtstamps));
hwtstamps->hwtstamp = ns_to_ktime(ns);
}

Loading