1*b1906ceaSLachlan Hodges /* SPDX-License-Identifier: GPL-2.0-only */ 2*b1906ceaSLachlan Hodges /* 3*b1906ceaSLachlan Hodges * Copyright (c) 2017-2026 Morse Micro 4*b1906ceaSLachlan Hodges */ 5*b1906ceaSLachlan Hodges 6*b1906ceaSLachlan Hodges #ifndef _MM81X_SKBQ_H_ 7*b1906ceaSLachlan Hodges #define _MM81X_SKBQ_H_ 8*b1906ceaSLachlan Hodges 9*b1906ceaSLachlan Hodges #include <linux/skbuff.h> 10*b1906ceaSLachlan Hodges #include <linux/workqueue.h> 11*b1906ceaSLachlan Hodges #include "rate_code.h" 12*b1906ceaSLachlan Hodges 13*b1906ceaSLachlan Hodges /* Sync value of skb header to indicate a valid skb */ 14*b1906ceaSLachlan Hodges #define MM81X_SKB_HEADER_SYNC (0xAA) 15*b1906ceaSLachlan Hodges /* Sync value indicating that the chip owns this skb */ 16*b1906ceaSLachlan Hodges #define MM81X_SKB_HEADER_CHIP_OWNED_SYNC (0xBB) 17*b1906ceaSLachlan Hodges 18*b1906ceaSLachlan Hodges enum mm81x_tx_status_and_conf_flags { 19*b1906ceaSLachlan Hodges MM81X_TX_STATUS_FLAGS_NO_ACK = BIT(0), 20*b1906ceaSLachlan Hodges MM81X_TX_STATUS_FLAGS_NO_REPORT = BIT(1), 21*b1906ceaSLachlan Hodges MM81X_TX_CONF_FLAGS_CTL_AMPDU = BIT(2), 22*b1906ceaSLachlan Hodges MM81X_TX_CONF_FLAGS_HW_ENCRYPT = BIT(3), 23*b1906ceaSLachlan Hodges MM81X_TX_CONF_FLAGS_VIF_ID = (BIT(4) | BIT(5) | BIT(6) | BIT(7) | 24*b1906ceaSLachlan Hodges BIT(8) | BIT(9) | BIT(10) | BIT(11)), 25*b1906ceaSLachlan Hodges MM81X_TX_CONF_FLAGS_KEY_IDX = (BIT(12) | BIT(13) | BIT(14)), 26*b1906ceaSLachlan Hodges MM81X_TX_STATUS_FLAGS_PS_FILTERED = (BIT(15)), 27*b1906ceaSLachlan Hodges MM81X_TX_CONF_IGNORE_TWT = (BIT(16)), 28*b1906ceaSLachlan Hodges MM81X_TX_STATUS_PAGE_INVALID = (BIT(17)), 29*b1906ceaSLachlan Hodges MM81X_TX_CONF_NO_PS_BUFFER = (BIT(18)), 30*b1906ceaSLachlan Hodges MM81X_TX_STATUS_DUTY_CYCLE_CANT_SEND = (BIT(19)), 31*b1906ceaSLachlan Hodges MM81X_TX_CONF_HAS_PV1_BPN_IN_BODY = (BIT(21)), 32*b1906ceaSLachlan Hodges MM81X_TX_CONF_FLAGS_SEND_AFTER_DTIM = (BIT(22)), 33*b1906ceaSLachlan Hodges MM81X_TX_STATUS_WAS_AGGREGATED = (BIT(23)), 34*b1906ceaSLachlan Hodges MM81X_TX_CONF_FLAGS_FULLMAC_REPORT = BIT(24), 35*b1906ceaSLachlan Hodges MM81X_TX_CONF_FLAGS_IMMEDIATE_REPORT = (BIT(31)) 36*b1906ceaSLachlan Hodges }; 37*b1906ceaSLachlan Hodges 38*b1906ceaSLachlan Hodges /* Getter and setter macros for vif id */ 39*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_VIF_ID_MASK (0xFF) 40*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_VIF_ID_SET(x) \ 41*b1906ceaSLachlan Hodges (((x) & MM81X_TX_CONF_FLAGS_VIF_ID_MASK) << 4) 42*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_VIF_ID_GET(x) \ 43*b1906ceaSLachlan Hodges (((x) & MM81X_TX_CONF_FLAGS_VIF_ID) >> 4) 44*b1906ceaSLachlan Hodges 45*b1906ceaSLachlan Hodges /* Getter and setter macros for key index */ 46*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_KEY_IDX_SET(x) (((x) & 0x07) << 12) 47*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_KEY_IDX_GET(x) \ 48*b1906ceaSLachlan Hodges (((x) & MM81X_TX_CONF_FLAGS_KEY_IDX) >> 12) 49*b1906ceaSLachlan Hodges 50*b1906ceaSLachlan Hodges enum mm81x_rx_status_flags { 51*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_ERROR = BIT(0), 52*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_DECRYPTED = BIT(1), 53*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_FCS_INCLUDED = BIT(2), 54*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_EOF = BIT(3), 55*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_AMPDU = BIT(4), 56*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_NDP = BIT(7), 57*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_UPLINK = BIT(8), 58*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_RI = (BIT(9) | BIT(10)), 59*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_NDP_TYPE = (BIT(11) | BIT(12) | BIT(13)), 60*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_CRC_ERROR = BIT(14), 61*b1906ceaSLachlan Hodges MM81X_RX_STATUS_FLAGS_VIF_ID = GENMASK(24, 17), 62*b1906ceaSLachlan Hodges }; 63*b1906ceaSLachlan Hodges 64*b1906ceaSLachlan Hodges /* Getter and Setter macros for vif id */ 65*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_MASK (0xFF) 66*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_SET(x) \ 67*b1906ceaSLachlan Hodges (((x) & MM81X_RX_STATUS_FLAGS_VIF_ID_MASK) << 17) 68*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_GET(x) \ 69*b1906ceaSLachlan Hodges (((x) & MM81X_RX_STATUS_FLAGS_VIF_ID) >> 17) 70*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_CLEAR(x) \ 71*b1906ceaSLachlan Hodges ((x) & ~(MM81X_RX_STATUS_FLAGS_VIF_ID_MASK << 17)) 72*b1906ceaSLachlan Hodges 73*b1906ceaSLachlan Hodges /* Getter macro for guard interval */ 74*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_UPL_IND_GET(x) \ 75*b1906ceaSLachlan Hodges (((x) & MM81X_RX_STATUS_FLAGS_UPLINK) >> 8) 76*b1906ceaSLachlan Hodges 77*b1906ceaSLachlan Hodges /* Getter macro for response indication */ 78*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_RI_GET(x) (((x) & MM81X_RX_STATUS_FLAGS_RI) >> 9) 79*b1906ceaSLachlan Hodges 80*b1906ceaSLachlan Hodges /* Getter macro for NDP type */ 81*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_NDP_TYPE_GET(x) \ 82*b1906ceaSLachlan Hodges (((x) & MM81X_RX_STATUS_FLAGS_NDP_TYPE) >> 11) 83*b1906ceaSLachlan Hodges 84*b1906ceaSLachlan Hodges enum mm81x_skb_channel { 85*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_DATA = 0x0, 86*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_NDP_FRAMES = 0x1, 87*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_DATA_NOACK = 0x2, 88*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_BEACON = 0x3, 89*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_MGMT = 0x4, 90*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_INTERNAL_CRIT_BEACON = 0x80, 91*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_COMMAND = 0xFE, 92*b1906ceaSLachlan Hodges MM81X_SKB_CHAN_TX_STATUS = 0xFF 93*b1906ceaSLachlan Hodges }; 94*b1906ceaSLachlan Hodges 95*b1906ceaSLachlan Hodges #define MM81X_SKB_MAX_RATES (4) 96*b1906ceaSLachlan Hodges 97*b1906ceaSLachlan Hodges struct mm81x_skb_rate_info { 98*b1906ceaSLachlan Hodges mm81x_rate_code_t mm81x_ratecode; 99*b1906ceaSLachlan Hodges u8 count; 100*b1906ceaSLachlan Hodges } __packed; 101*b1906ceaSLachlan Hodges 102*b1906ceaSLachlan Hodges struct mm81x_skb_tx_status { 103*b1906ceaSLachlan Hodges __le32 flags; 104*b1906ceaSLachlan Hodges __le32 pkt_id; 105*b1906ceaSLachlan Hodges u8 tid; 106*b1906ceaSLachlan Hodges u8 channel; 107*b1906ceaSLachlan Hodges __le16 ampdu_info; 108*b1906ceaSLachlan Hodges struct mm81x_skb_rate_info rates[MM81X_SKB_MAX_RATES]; 109*b1906ceaSLachlan Hodges } __packed; 110*b1906ceaSLachlan Hodges 111*b1906ceaSLachlan Hodges #define MM81X_TXSTS_AMPDU_INFO_GET_TAG(x) (((x) >> 10) & 0x3F) 112*b1906ceaSLachlan Hodges #define MM81X_TXSTS_AMPDU_INFO_GET_LEN(x) (((x) >> 5) & 0x1F) 113*b1906ceaSLachlan Hodges #define MM81X_TXSTS_AMPDU_INFO_GET_SUC(x) ((x) & 0x1F) 114*b1906ceaSLachlan Hodges 115*b1906ceaSLachlan Hodges struct mm81x_skb_tx_info { 116*b1906ceaSLachlan Hodges __le32 flags; 117*b1906ceaSLachlan Hodges __le32 pkt_id; 118*b1906ceaSLachlan Hodges u8 tid; 119*b1906ceaSLachlan Hodges u8 tid_params; 120*b1906ceaSLachlan Hodges u8 mmss_params; 121*b1906ceaSLachlan Hodges u8 padding[1]; 122*b1906ceaSLachlan Hodges struct mm81x_skb_rate_info rates[MM81X_SKB_MAX_RATES]; 123*b1906ceaSLachlan Hodges } __packed; 124*b1906ceaSLachlan Hodges 125*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_MAX_REORDER_BUF 0x1f 126*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_AMPDU_ENABLED 0x20 127*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_AMSDU_SUPPORTED 0x40 128*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_USE_LEGACY_BA 0x80 129*b1906ceaSLachlan Hodges 130*b1906ceaSLachlan Hodges /* Bitmap for MMSS (Minimum MPDU start spacing) parameters 131*b1906ceaSLachlan Hodges * +-----------+-----------+ 132*b1906ceaSLachlan Hodges * | Morse | MMSS set | 133*b1906ceaSLachlan Hodges * | MMSS | by S1G cap| 134*b1906ceaSLachlan Hodges * | offset | IE | 135*b1906ceaSLachlan Hodges * |-----------|-----------| 136*b1906ceaSLachlan Hodges * |b7|b6|b5|b4|b3|b2|b1|b0| 137*b1906ceaSLachlan Hodges */ 138*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_MMSS_MASK GENMASK(3, 0) 139*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_MMSS_OFFSET_START 4 140*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_MMSS_OFFSET_MASK GENMASK(7, 4) 141*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_SET_MMSS(x) ((x) & TX_INFO_MMSS_PARAMS_MMSS_MASK) 142*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_SET_MMSS_OFFSET(x) \ 143*b1906ceaSLachlan Hodges (((x) << TX_INFO_MMSS_PARAMS_MMSS_OFFSET_START) & \ 144*b1906ceaSLachlan Hodges TX_INFO_MMSS_PARAMS_MMSS_OFFSET_MASK) 145*b1906ceaSLachlan Hodges 146*b1906ceaSLachlan Hodges struct mm81x_skb_rx_status { 147*b1906ceaSLachlan Hodges __le32 flags; 148*b1906ceaSLachlan Hodges mm81x_rate_code_t mm81x_ratecode; 149*b1906ceaSLachlan Hodges __le16 rssi; 150*b1906ceaSLachlan Hodges __le16 freq_100khz; 151*b1906ceaSLachlan Hodges u8 bss_color; 152*b1906ceaSLachlan Hodges s8 noise_dbm; 153*b1906ceaSLachlan Hodges /** Padding for word alignment */ 154*b1906ceaSLachlan Hodges u8 padding[2]; 155*b1906ceaSLachlan Hodges __le64 rx_timestamp_us; 156*b1906ceaSLachlan Hodges } __packed; 157*b1906ceaSLachlan Hodges 158*b1906ceaSLachlan Hodges struct mm81x_skb_hdr { 159*b1906ceaSLachlan Hodges u8 sync; 160*b1906ceaSLachlan Hodges u8 channel; 161*b1906ceaSLachlan Hodges __le16 len; 162*b1906ceaSLachlan Hodges u8 offset; 163*b1906ceaSLachlan Hodges u8 checksum_lower; 164*b1906ceaSLachlan Hodges __le16 checksum_upper; 165*b1906ceaSLachlan Hodges union { 166*b1906ceaSLachlan Hodges struct mm81x_skb_tx_info tx_info; 167*b1906ceaSLachlan Hodges struct mm81x_skb_tx_status tx_status; 168*b1906ceaSLachlan Hodges struct mm81x_skb_rx_status rx_status; 169*b1906ceaSLachlan Hodges }; 170*b1906ceaSLachlan Hodges } __packed; 171*b1906ceaSLachlan Hodges 172*b1906ceaSLachlan Hodges #define MM81X_SKBQ_SIZE (4 * 128 * 1024) 173*b1906ceaSLachlan Hodges 174*b1906ceaSLachlan Hodges struct mm81x; 175*b1906ceaSLachlan Hodges 176*b1906ceaSLachlan Hodges struct mm81x_skbq { 177*b1906ceaSLachlan Hodges struct mm81x *mors; 178*b1906ceaSLachlan Hodges u32 pkt_seq; /* SKB sequence used in tx_status */ 179*b1906ceaSLachlan Hodges u16 flags; 180*b1906ceaSLachlan Hodges u32 skbq_size; /* current off loaded size */ 181*b1906ceaSLachlan Hodges spinlock_t lock; 182*b1906ceaSLachlan Hodges struct sk_buff_head skbq; 183*b1906ceaSLachlan Hodges struct sk_buff_head pending; /* packets sent pending feedback */ 184*b1906ceaSLachlan Hodges struct work_struct dispatch_work; 185*b1906ceaSLachlan Hodges }; 186*b1906ceaSLachlan Hodges 187*b1906ceaSLachlan Hodges void mm81x_skbq_purge(struct mm81x_skbq *mq, struct sk_buff_head *skbq); 188*b1906ceaSLachlan Hodges void mm81x_skbq_purge_aged(struct mm81x *mors, struct mm81x_skbq *mq); 189*b1906ceaSLachlan Hodges u32 mm81x_skbq_space(struct mm81x_skbq *mq); 190*b1906ceaSLachlan Hodges u32 mm81x_skbq_size(struct mm81x_skbq *mq); 191*b1906ceaSLachlan Hodges int mm81x_skbq_deq_num_skb(struct mm81x_skbq *mq, struct sk_buff_head *skbq, 192*b1906ceaSLachlan Hodges int num_skb); 193*b1906ceaSLachlan Hodges struct sk_buff *mm81x_skbq_alloc_skb(struct mm81x_skbq *mq, 194*b1906ceaSLachlan Hodges unsigned int length); 195*b1906ceaSLachlan Hodges int mm81x_skbq_skb_tx(struct mm81x_skbq *mq, struct sk_buff **skb, 196*b1906ceaSLachlan Hodges struct mm81x_skb_tx_info *tx_info, u8 channel); 197*b1906ceaSLachlan Hodges int mm81x_skbq_put(struct mm81x_skbq *mq, struct sk_buff *skb); 198*b1906ceaSLachlan Hodges void mm81x_skbq_enq(struct mm81x_skbq *mq, struct sk_buff_head *skbq); 199*b1906ceaSLachlan Hodges void mm81x_skbq_enq_prepend(struct mm81x_skbq *mq, struct sk_buff_head *skbq); 200*b1906ceaSLachlan Hodges void mm81x_skbq_tx_complete(struct mm81x_skbq *mq, struct sk_buff_head *skbq); 201*b1906ceaSLachlan Hodges struct sk_buff *mm81x_skbq_tx_pending(struct mm81x_skbq *mq); 202*b1906ceaSLachlan Hodges void mm81x_skbq_init(struct mm81x *mors, struct mm81x_skbq *mq, u16 flags); 203*b1906ceaSLachlan Hodges void mm81x_skbq_finish(struct mm81x_skbq *mq); 204*b1906ceaSLachlan Hodges void mm81x_skbq_pull_hdr_post_tx(struct sk_buff *skb); 205*b1906ceaSLachlan Hodges void mm81x_skbq_mon_dump(struct mm81x *mors, struct seq_file *file); 206*b1906ceaSLachlan Hodges void mm81x_skbq_skb_finish(struct mm81x_skbq *mq, struct sk_buff *skb, 207*b1906ceaSLachlan Hodges struct mm81x_skb_tx_status *tx_sts); 208*b1906ceaSLachlan Hodges void mm81x_skbq_tx_flush(struct mm81x_skbq *mq); 209*b1906ceaSLachlan Hodges int mm81x_skbq_check_for_stale_tx(struct mm81x *mors, struct mm81x_skbq *mq); 210*b1906ceaSLachlan Hodges void mm81x_skbq_may_wake_tx_queues(struct mm81x *mors); 211*b1906ceaSLachlan Hodges u32 mm81x_skbq_count_tx_ready(struct mm81x_skbq *mq); 212*b1906ceaSLachlan Hodges u32 mm81x_skbq_count(struct mm81x_skbq *mq); 213*b1906ceaSLachlan Hodges u32 mm81x_skbq_pending_count(struct mm81x_skbq *mq); 214*b1906ceaSLachlan Hodges void mm81x_skbq_data_traffic_pause(struct mm81x *mors); 215*b1906ceaSLachlan Hodges void mm81x_skbq_data_traffic_resume(struct mm81x *mors); 216*b1906ceaSLachlan Hodges bool mm81x_skbq_validate_checksum(u8 *data); 217*b1906ceaSLachlan Hodges 218*b1906ceaSLachlan Hodges #endif /* !_MM81X_SKBQ_H_ */ 219