| /* 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_ */ |