blob: 1a47c8c5b5302637d34cbd242b100d37d6e8fa3f [file] [edit]
/* 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_ */