/* SPDX-License-Identifier: GPL-2.0 */
|
|
/******************************************************************************
|
*
|
* Copyright (C) 2020 SeekWave Technology Co.,Ltd.
|
*
|
* This program is free software; you can redistribute it and/or modify
|
* it under the terms of version 2 of the GNU General Public License as
|
* published by the Free Software Foundation;
|
*
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
*
|
******************************************************************************/
|
|
#ifndef __SKW_RX_H__
|
#define __SKW_RX_H__
|
|
#include <net/ieee80211_radiotap.h>
|
|
#include "skw_platform_data.h"
|
#include "skw_iface.h"
|
#include "skw_core.h"
|
#include "skw_tx.h"
|
|
#define SKW_MAX_AMPDU_BUF_SIZE 0x100 /* 256 */
|
|
#define SKW_AMSDU_FLAG_TAINT BIT(0)
|
#define SKW_AMSDU_FLAG_VALID BIT(1)
|
|
#define SKW_SDIO_RX_DESC_HDR_OFFSET 0
|
#define SKW_SDIO_RX_DESC_MSDU_OFFSET 52
|
#define SKW_USB_RX_DESC_HDR_OFFSET 52
|
#define SKW_USB_RX_DESC_MSDU_OFFSET 0
|
#define SKW_PCIE_RX_DESC_HDR_OFFSET 44
|
#define SKW_PCIE_RX_DESC_MSDU_OFFSET 8
|
|
#ifndef ETH_P_80211_RAW
|
#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
|
#endif
|
|
enum SKW_RELEASE_REASON {
|
SKW_RELEASE_INVALID,
|
SKW_RELEASE_EXPIRED,
|
SKW_RELEASE_OOB,
|
SKW_RELEASE_BAR,
|
SKW_RELEASE_FREE,
|
};
|
|
struct skw_skb_rxcb {
|
unsigned long rx_time;
|
u16 rx_desc_offset;
|
u8 amsdu_bitmap;
|
u8 amsdu_mask;
|
u16 amsdu_flags;
|
u8 skw_created;
|
u8 lmac_id;
|
u8 skip_replay_detect;
|
};
|
|
struct skw_drop_sn_info {
|
u16 sn;
|
u8 amsdu_idx;
|
u8 amsdu_first: 1;
|
u8 amsdu_last: 1;
|
u8 is_amsdu: 1;
|
u8 qos: 1;
|
u8 tid: 4;
|
u32 peer_idx: 5;
|
u32 inst: 2;
|
u32 resved: 25;
|
} __packed;
|
|
struct skw_rx_desc {
|
/* word 13 */
|
u16 eosp:1;
|
u16 more_data:1;
|
u16 pm:1;
|
u16 retry_frame:1;
|
u16 is_eof:1; //mpdu_eof_flag
|
u16 ba_session:1;
|
u16 resv1:1;
|
u16 resv:1;
|
u16 cipher:4;
|
u16 snap_type:1;
|
u16 vlan:1;
|
u16 eapol:1;
|
u16 rcv_in_ps_mode:1;
|
u16 msdu_len;
|
|
/* word 14 */
|
u8 csum_valid:1;
|
u8 is_ampdu:1;
|
u8 snap_match:1;
|
u8 is_amsdu:1;
|
u8 is_qos_data:1;
|
u8 amsdu_first_idx:1;
|
u8 amsdu_last_idx:1;
|
u8 mpdu_sniff:1;
|
u16 csum;
|
u8 msdu_filter;
|
|
/* word 15 */
|
u16 sn:12; /* seq number */
|
u16 frag_num:4;
|
u16 inst_id:2; //mpdu_ra_index
|
u16 inst_id_valid:1;
|
u16 more_frag:1;
|
u16 peer_idx:5;
|
u16 peer_idx_valid:1;
|
u16 is_mc_addr:1; //bc_mc_flag
|
u16 first_msdu_in_buff:1;
|
u16 tid:4;
|
|
/* word 16 & word17*/
|
u8 pn[6]; //u16 msdu_len; //32:47
|
u8 msdu_offset;
|
u8 amsdu_idx:6;
|
u16 need_forward:1;//da_ra_diff
|
u16 mac_drop_frag:1;
|
} __packed;
|
|
struct skw_phy_rx_desc {
|
/* word 8 */
|
u32 lgacy_len:12;
|
u32 psdu_len:20;
|
|
/* word 9 */
|
u32 flock_rssi0:11;
|
u32 flock_rssi1:11;
|
u32 lp_snr0:7;
|
u32 nss:2;
|
u32 sigb_dcm:1;
|
|
/* word 10 */
|
u32 full_rssi0:11;
|
u32 full_rssi1:11;
|
u32 lp_snr1:7;
|
u32 sbw:3;
|
|
/* word 11 */
|
u8 agc_gain0;
|
u8 agc_gain1;
|
u8 ppdu_mode:4;
|
u8 dcm:1;
|
u8 gi_type:2;
|
u8 fec_coding:1;
|
u8 data_rate:6;
|
u8 ess_n_est_ss:2;
|
|
/* word 12 */
|
u16 sta_id:11;
|
u16 ru_size:3;
|
u16 he_sigb_comp:1;
|
u16 doppler:1;
|
u16 sr4:4;
|
u16 sr3:4;
|
u16 sr2:4;
|
u16 sr1:4;
|
|
/* word 13 */
|
u16 grp_id:6;
|
u16 partial_aid:9;
|
u16 befmed:1;
|
u16 top_dura:14;
|
u16 ltf_type:2;
|
|
/* word 14 */
|
u8 ch1_agc_gain0;
|
u8 ch1_agc_gain1;
|
u16 serv_field;
|
|
/* word 15 */
|
u32 sfo_ppm_init:24;
|
u32 plcp_delay:8;
|
|
/* word 16 */
|
u32 slock_rssi0:11;
|
u32 slock_rssi2:11;
|
u32 nsts:2;
|
u32 bss_color:6;
|
u32 tgnf_flag0:1;
|
u32 tgnf_flag1:1;
|
|
/* word 17 */
|
u8 ofdma:1;
|
u8 mimo:1;
|
u8 sifb_mcs:3;
|
u8 pe_dur:3;
|
u8 user_num:7;
|
u8 stbc:1;
|
u16 mu3_nsts:3;
|
u16 mu2_nsts:3;
|
u16 mu1_nsts:3;
|
u16 mu0_nsts:3;
|
u16 ltf_num:2;
|
u16 mimo_ofdma:1;
|
u16 resv8:1;
|
|
};
|
|
struct skw_sniffer_desc {
|
u32 resv1;
|
/* word 4 */
|
u8 mac_hdr_proc:7;
|
u8 sniff_flag:1;
|
u8 mpdu_proc_status;
|
u8 buf_num_mpdu;
|
u8 mac_hdr_len:6;
|
u8 dir_data_sniff:1;
|
u8 resv2:1;
|
|
/* word 5 */
|
u16 mpdu_len:14;
|
u16 resv3:2;
|
u16 psdu_cnt;
|
|
/* word 6 */
|
u8 sniff_rsv_num;
|
u8 resv4:1;
|
u8 is_ampdu:1;
|
u8 is_amsdu:1;
|
u8 mpdu2host:1;
|
u8 mpdu_defrag:1;
|
u8 mpdu_uc:1;
|
u8 mpdu_bc:1;
|
u8 resv5:1;
|
u8 peer_lut_idx:5;
|
u8 peer_lut_idx_vaild:1;
|
u8 resv6:2;
|
u8 cipher:4;
|
u8 inst_id:2; //mpdu_ra_index
|
u8 inst_id_vaild:1;
|
u8 resv7:1;
|
|
/* word 7 */
|
u16 sniff_status:12;
|
u16 pad_len:4;
|
u16 sn:12;
|
u16 frag_num:4;
|
|
/* word 8 - 17 */
|
struct skw_phy_rx_desc phy_desc;
|
} __packed;
|
|
struct skw_radiotap_desc {
|
struct ieee80211_radiotap_header radiotap_hdr;
|
u8 radiotap_flag;
|
} __packed;
|
|
static inline void skw_snap_unmatch_handler(struct sk_buff *skb)
|
{
|
skb_reset_mac_header(skb);
|
eth_hdr(skb)->h_proto = htons(skb->len & 0xffff);
|
}
|
|
static inline void skw_event_add_credit(struct skw_core *skw, void *data)
|
{
|
u16 *credit = data;
|
|
skw_add_credit(skw, 0, *credit);
|
skw_add_credit(skw, 1, *(credit + 1));
|
}
|
|
static inline void skw_data_add_credit(struct skw_core *skw, void *data)
|
{
|
}
|
|
static inline bool is_skw_monitor_data(struct skw_core *skw, void *data)
|
{
|
struct skw_sniffer_desc *desc = NULL;
|
|
if (skw->hw.bus == SKW_BUS_USB)
|
desc = (struct skw_sniffer_desc *)((u8 *)(data + 12)); //offset word0 ~ word2
|
else if (skw->hw.bus == SKW_BUS_SDIO)
|
desc = (struct skw_sniffer_desc *)((u8 *)(data));
|
else if (skw->hw.bus == SKW_BUS_PCIE) //TODO
|
return false;
|
|
if (!desc)
|
return -EINVAL;
|
|
skw_detail("sniffer flag:%d\n", desc->sniff_flag);
|
|
if (desc->sniff_flag) {
|
skw_detail("recv sniffer data, desc len:%ld\n", sizeof(struct skw_sniffer_desc));
|
return true;
|
}
|
|
return false;
|
}
|
|
static inline struct skw_skb_rxcb *SKW_SKB_RXCB(struct sk_buff *skb)
|
{
|
return (struct skw_skb_rxcb *)skb->cb;
|
}
|
|
int skw_add_tid_rx(struct skw_peer *peer, u16 tid, u16 ssn, u16 buf_size);
|
int skw_update_tid_rx(struct skw_peer *peer, u16 tid, u16 ssn, u16 win_size);
|
int skw_del_tid_rx(struct skw_peer *peer, u16 tid);
|
|
int skw_rx_process(struct skw_core *skw,
|
struct sk_buff_head *rx_dat_q, struct skw_list *rx_todo_list);
|
void skw_rx_todo(struct skw_list *todo_list);
|
|
int skw_rx_init(struct skw_core *skw);
|
int skw_rx_deinit(struct skw_core *skw);
|
int skw_rx_cb(int port, struct scatterlist *sglist, int nents, void *priv);
|
int skw_register_rx_callback(struct skw_core *skw, void *cmd_cb, void *cmd_ctx,
|
void *dat_cb, void *dat_ctx);
|
|
#endif
|