1*73b01e57SJeff Chen /* SPDX-License-Identifier: GPL-2.0-only */
2*73b01e57SJeff Chen /*
3*73b01e57SJeff Chen * NXP Wireless LAN device driver: utility functions
4*73b01e57SJeff Chen *
5*73b01e57SJeff Chen * Copyright 2011-2024 NXP
6*73b01e57SJeff Chen */
7*73b01e57SJeff Chen
8*73b01e57SJeff Chen #ifndef _NXPWIFI_UTIL_H_
9*73b01e57SJeff Chen #define _NXPWIFI_UTIL_H_
10*73b01e57SJeff Chen #include "fw.h"
11*73b01e57SJeff Chen
12*73b01e57SJeff Chen struct nxpwifi_adapter;
13*73b01e57SJeff Chen
14*73b01e57SJeff Chen struct nxpwifi_private;
15*73b01e57SJeff Chen
16*73b01e57SJeff Chen struct nxpwifi_dma_mapping {
17*73b01e57SJeff Chen dma_addr_t addr;
18*73b01e57SJeff Chen size_t len;
19*73b01e57SJeff Chen };
20*73b01e57SJeff Chen
21*73b01e57SJeff Chen struct nxpwifi_cb {
22*73b01e57SJeff Chen struct nxpwifi_dma_mapping dma_mapping;
23*73b01e57SJeff Chen union {
24*73b01e57SJeff Chen struct nxpwifi_rxinfo rx_info;
25*73b01e57SJeff Chen struct nxpwifi_txinfo tx_info;
26*73b01e57SJeff Chen };
27*73b01e57SJeff Chen };
28*73b01e57SJeff Chen
29*73b01e57SJeff Chen /* size/addr for nxpwifi_debug_info */
30*73b01e57SJeff Chen #define item_size(n) (sizeof_field(struct nxpwifi_debug_info, n))
31*73b01e57SJeff Chen #define item_addr(n) (offsetof(struct nxpwifi_debug_info, n))
32*73b01e57SJeff Chen
33*73b01e57SJeff Chen /* size/addr for struct nxpwifi_adapter */
34*73b01e57SJeff Chen #define adapter_item_size(n) (sizeof_field(struct nxpwifi_adapter, n))
35*73b01e57SJeff Chen #define adapter_item_addr(n) (offsetof(struct nxpwifi_adapter, n))
36*73b01e57SJeff Chen
37*73b01e57SJeff Chen struct nxpwifi_debug_data {
38*73b01e57SJeff Chen char name[32]; /* variable/array name */
39*73b01e57SJeff Chen u32 size; /* size of the variable/array */
40*73b01e57SJeff Chen size_t addr; /* address of the variable/array */
41*73b01e57SJeff Chen int num; /* number of variables in an array */
42*73b01e57SJeff Chen };
43*73b01e57SJeff Chen
NXPWIFI_SKB_RXCB(struct sk_buff * skb)44*73b01e57SJeff Chen static inline struct nxpwifi_rxinfo *NXPWIFI_SKB_RXCB(struct sk_buff *skb)
45*73b01e57SJeff Chen {
46*73b01e57SJeff Chen struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;
47*73b01e57SJeff Chen
48*73b01e57SJeff Chen BUILD_BUG_ON(sizeof(struct nxpwifi_cb) > sizeof(skb->cb));
49*73b01e57SJeff Chen return &cb->rx_info;
50*73b01e57SJeff Chen }
51*73b01e57SJeff Chen
NXPWIFI_SKB_TXCB(struct sk_buff * skb)52*73b01e57SJeff Chen static inline struct nxpwifi_txinfo *NXPWIFI_SKB_TXCB(struct sk_buff *skb)
53*73b01e57SJeff Chen {
54*73b01e57SJeff Chen struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;
55*73b01e57SJeff Chen
56*73b01e57SJeff Chen return &cb->tx_info;
57*73b01e57SJeff Chen }
58*73b01e57SJeff Chen
nxpwifi_store_mapping(struct sk_buff * skb,struct nxpwifi_dma_mapping * mapping)59*73b01e57SJeff Chen static inline void nxpwifi_store_mapping(struct sk_buff *skb,
60*73b01e57SJeff Chen struct nxpwifi_dma_mapping *mapping)
61*73b01e57SJeff Chen {
62*73b01e57SJeff Chen struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;
63*73b01e57SJeff Chen
64*73b01e57SJeff Chen memcpy(&cb->dma_mapping, mapping, sizeof(*mapping));
65*73b01e57SJeff Chen }
66*73b01e57SJeff Chen
nxpwifi_get_mapping(struct sk_buff * skb,struct nxpwifi_dma_mapping * mapping)67*73b01e57SJeff Chen static inline void nxpwifi_get_mapping(struct sk_buff *skb,
68*73b01e57SJeff Chen struct nxpwifi_dma_mapping *mapping)
69*73b01e57SJeff Chen {
70*73b01e57SJeff Chen struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;
71*73b01e57SJeff Chen
72*73b01e57SJeff Chen memcpy(mapping, &cb->dma_mapping, sizeof(*mapping));
73*73b01e57SJeff Chen }
74*73b01e57SJeff Chen
NXPWIFI_SKB_DMA_ADDR(struct sk_buff * skb)75*73b01e57SJeff Chen static inline dma_addr_t NXPWIFI_SKB_DMA_ADDR(struct sk_buff *skb)
76*73b01e57SJeff Chen {
77*73b01e57SJeff Chen struct nxpwifi_dma_mapping mapping;
78*73b01e57SJeff Chen
79*73b01e57SJeff Chen nxpwifi_get_mapping(skb, &mapping);
80*73b01e57SJeff Chen
81*73b01e57SJeff Chen return mapping.addr;
82*73b01e57SJeff Chen }
83*73b01e57SJeff Chen
84*73b01e57SJeff Chen int nxpwifi_debug_info_to_buffer(struct nxpwifi_private *priv, char *buf,
85*73b01e57SJeff Chen struct nxpwifi_debug_info *info);
86*73b01e57SJeff Chen
le16_unaligned_add_cpu(__le16 * var,u16 val)87*73b01e57SJeff Chen static inline void le16_unaligned_add_cpu(__le16 *var, u16 val)
88*73b01e57SJeff Chen {
89*73b01e57SJeff Chen put_unaligned_le16(get_unaligned_le16(var) + val, var);
90*73b01e57SJeff Chen }
91*73b01e57SJeff Chen
92*73b01e57SJeff Chen /*
93*73b01e57SJeff Chen * Iterate over TLVs safely.
94*73b01e57SJeff Chen * Ensures no out-of-bound access even if firmware sends malformed data.
95*73b01e57SJeff Chen */
96*73b01e57SJeff Chen #define nxpwifi_for_each_tlv(tlv, buf, buf_len) \
97*73b01e57SJeff Chen for (tlv = (const struct nxpwifi_tlv *)(buf); \
98*73b01e57SJeff Chen (u8 *)(tlv) + sizeof(*tlv) <= (u8 *)(buf) + (buf_len) && \
99*73b01e57SJeff Chen (u8 *)(tlv) + sizeof(*tlv) + le16_to_cpu(tlv->len) <= \
100*73b01e57SJeff Chen (u8 *)(buf) + (buf_len); \
101*73b01e57SJeff Chen tlv = (const struct nxpwifi_tlv *)((u8 *)(tlv) + sizeof(*tlv) + \
102*73b01e57SJeff Chen le16_to_cpu(tlv->len)))
103*73b01e57SJeff Chen
104*73b01e57SJeff Chen /* Return first TLV matching @type in given buffer. */
105*73b01e57SJeff Chen static inline const struct nxpwifi_tlv *
nxpwifi_find_tlv(u16 type,const u8 * buf,u32 buf_len)106*73b01e57SJeff Chen nxpwifi_find_tlv(u16 type, const u8 *buf, u32 buf_len)
107*73b01e57SJeff Chen {
108*73b01e57SJeff Chen const struct nxpwifi_tlv *tlv;
109*73b01e57SJeff Chen
110*73b01e57SJeff Chen nxpwifi_for_each_tlv(tlv, buf, buf_len) {
111*73b01e57SJeff Chen if (le16_to_cpu(tlv->type) == type)
112*73b01e57SJeff Chen return tlv;
113*73b01e57SJeff Chen }
114*73b01e57SJeff Chen
115*73b01e57SJeff Chen return NULL;
116*73b01e57SJeff Chen }
117*73b01e57SJeff Chen
118*73b01e57SJeff Chen int nxpwifi_append_data_tlv(u16 id, u8 *data, int len, u8 *pos, u8 *cmd_end);
119*73b01e57SJeff Chen
120*73b01e57SJeff Chen int nxpwifi_download_vdll_block(struct nxpwifi_adapter *adapter,
121*73b01e57SJeff Chen u8 *block, u16 block_len);
122*73b01e57SJeff Chen
123*73b01e57SJeff Chen int nxpwifi_process_vdll_event(struct nxpwifi_private *priv,
124*73b01e57SJeff Chen struct sk_buff *skb);
125*73b01e57SJeff Chen
126*73b01e57SJeff Chen u64 nxpwifi_roc_cookie(struct nxpwifi_adapter *adapter);
127*73b01e57SJeff Chen
128*73b01e57SJeff Chen void nxpwifi_queue_work(struct nxpwifi_adapter *adapter,
129*73b01e57SJeff Chen struct work_struct *work);
130*73b01e57SJeff Chen
131*73b01e57SJeff Chen void nxpwifi_queue_delayed_work(struct nxpwifi_adapter *adapter,
132*73b01e57SJeff Chen struct delayed_work *dwork,
133*73b01e57SJeff Chen unsigned long delay);
134*73b01e57SJeff Chen
135*73b01e57SJeff Chen void nxpwifi_queue_wiphy_work(struct nxpwifi_adapter *adapter,
136*73b01e57SJeff Chen struct wiphy_work *work);
137*73b01e57SJeff Chen
138*73b01e57SJeff Chen void nxpwifi_queue_delayed_wiphy_work(struct nxpwifi_adapter *adapter,
139*73b01e57SJeff Chen struct wiphy_delayed_work *dwork,
140*73b01e57SJeff Chen unsigned long delay);
141*73b01e57SJeff Chen
142*73b01e57SJeff Chen /*
143*73b01e57SJeff Chen * Firmware cannot run AP and STA on different channels simultaneously,
144*73b01e57SJeff Chen * and doing so may trigger a crash. Check whether check_chan can be set
145*73b01e57SJeff Chen * safely; return true if allowed, false if another channel is already
146*73b01e57SJeff Chen * active in firmware.
147*73b01e57SJeff Chen */
148*73b01e57SJeff Chen bool nxpwifi_is_channel_setting_allowable(struct nxpwifi_private *priv,
149*73b01e57SJeff Chen struct ieee80211_channel *check_chan);
150*73b01e57SJeff Chen
151*73b01e57SJeff Chen void nxpwifi_convert_chan_to_band_cfg(struct nxpwifi_private *priv,
152*73b01e57SJeff Chen u8 *band_cfg,
153*73b01e57SJeff Chen struct cfg80211_chan_def *chan_def);
154*73b01e57SJeff Chen
155*73b01e57SJeff Chen #endif /* !_NXPWIFI_UTIL_H_ */
156