summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/nxp/nxpwifi/util.h
blob: 1a47c8c5b5302637d34cbd242b100d37d6e8fa3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * NXP Wireless LAN device driver: utility functions
 *
 * Copyright 2011-2024 NXP
 */

#ifndef _NXPWIFI_UTIL_H_
#define _NXPWIFI_UTIL_H_
#include "fw.h"

struct nxpwifi_adapter;

struct nxpwifi_private;

struct nxpwifi_dma_mapping {
	dma_addr_t addr;
	size_t len;
};

struct nxpwifi_cb {
	struct nxpwifi_dma_mapping dma_mapping;
	union {
		struct nxpwifi_rxinfo rx_info;
		struct nxpwifi_txinfo tx_info;
	};
};

/* size/addr for nxpwifi_debug_info */
#define item_size(n)		(sizeof_field(struct nxpwifi_debug_info, n))
#define item_addr(n)		(offsetof(struct nxpwifi_debug_info, n))

/* size/addr for struct nxpwifi_adapter */
#define adapter_item_size(n)	(sizeof_field(struct nxpwifi_adapter, n))
#define adapter_item_addr(n)	(offsetof(struct nxpwifi_adapter, n))

struct nxpwifi_debug_data {
	char name[32];		/* variable/array name */
	u32 size;		/* size of the variable/array */
	size_t addr;		/* address of the variable/array */
	int num;		/* number of variables in an array */
};

static inline struct nxpwifi_rxinfo *NXPWIFI_SKB_RXCB(struct sk_buff *skb)
{
	struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;

	BUILD_BUG_ON(sizeof(struct nxpwifi_cb) > sizeof(skb->cb));
	return &cb->rx_info;
}

static inline struct nxpwifi_txinfo *NXPWIFI_SKB_TXCB(struct sk_buff *skb)
{
	struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;

	return &cb->tx_info;
}

static inline void nxpwifi_store_mapping(struct sk_buff *skb,
					 struct nxpwifi_dma_mapping *mapping)
{
	struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;

	memcpy(&cb->dma_mapping, mapping, sizeof(*mapping));
}

static inline void nxpwifi_get_mapping(struct sk_buff *skb,
				       struct nxpwifi_dma_mapping *mapping)
{
	struct nxpwifi_cb *cb = (struct nxpwifi_cb *)skb->cb;

	memcpy(mapping, &cb->dma_mapping, sizeof(*mapping));
}

static inline dma_addr_t NXPWIFI_SKB_DMA_ADDR(struct sk_buff *skb)
{
	struct nxpwifi_dma_mapping mapping;

	nxpwifi_get_mapping(skb, &mapping);

	return mapping.addr;
}

int nxpwifi_debug_info_to_buffer(struct nxpwifi_private *priv, char *buf,
				 struct nxpwifi_debug_info *info);

static inline void le16_unaligned_add_cpu(__le16 *var, u16 val)
{
	put_unaligned_le16(get_unaligned_le16(var) + val, var);
}

/*
 * Iterate over TLVs safely.
 * Ensures no out-of-bound access even if firmware sends malformed data.
 */
#define nxpwifi_for_each_tlv(tlv, buf, buf_len)				\
	for (tlv = (const struct nxpwifi_tlv *)(buf);				\
	     (u8 *)(tlv) + sizeof(*tlv) <= (u8 *)(buf) + (buf_len) &&		\
	     (u8 *)(tlv) + sizeof(*tlv) + le16_to_cpu(tlv->len) <=		\
	     (u8 *)(buf) + (buf_len);					\
	     tlv = (const struct nxpwifi_tlv *)((u8 *)(tlv) + sizeof(*tlv) +	\
	     le16_to_cpu(tlv->len)))

/* Return first TLV matching @type in given buffer. */
static inline const struct nxpwifi_tlv *
nxpwifi_find_tlv(u16 type, const u8 *buf, u32 buf_len)
{
	const struct nxpwifi_tlv *tlv;

	nxpwifi_for_each_tlv(tlv, buf, buf_len)	{
		if (le16_to_cpu(tlv->type) == type)
			return tlv;
	}

	return NULL;
}

int nxpwifi_append_data_tlv(u16 id, u8 *data, int len, u8 *pos, u8 *cmd_end);

int nxpwifi_download_vdll_block(struct nxpwifi_adapter *adapter,
				u8 *block, u16 block_len);

int nxpwifi_process_vdll_event(struct nxpwifi_private *priv,
			       struct sk_buff *skb);

u64 nxpwifi_roc_cookie(struct nxpwifi_adapter *adapter);

void nxpwifi_queue_work(struct nxpwifi_adapter *adapter,
			struct work_struct *work);

void nxpwifi_queue_delayed_work(struct nxpwifi_adapter *adapter,
				struct delayed_work *dwork,
				unsigned long delay);

void nxpwifi_queue_wiphy_work(struct nxpwifi_adapter *adapter,
			      struct wiphy_work *work);

void nxpwifi_queue_delayed_wiphy_work(struct nxpwifi_adapter *adapter,
				      struct wiphy_delayed_work *dwork,
				      unsigned long delay);

/*
 * Firmware cannot run AP and STA on different channels simultaneously,
 * and doing so may trigger a crash. Check whether check_chan can be set
 * safely; return true if allowed, false if another channel is already
 * active in firmware.
 */
bool nxpwifi_is_channel_setting_allowable(struct nxpwifi_private *priv,
					  struct ieee80211_channel *check_chan);

void nxpwifi_convert_chan_to_band_cfg(struct nxpwifi_private *priv,
				      u8 *band_cfg,
				      struct cfg80211_chan_def *chan_def);

#endif /* !_NXPWIFI_UTIL_H_ */