xref: /linux/drivers/net/wireless/nxp/nxpwifi/util.h (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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