lin
2025-07-31 065ea569db06206874bbfa18eb25ff6121aec09b
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
/* 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_TX_H__
#define __SKW_TX_H__
 
#include <linux/virtio_ring.h>
 
#include "skw_platform_data.h"
 
/* used for tx descriptor */
#define SKW_ETHER_FRAME            0
#define SKW_80211_FRAME            1
 
#define SKW_SNAP_HDR_LEN           8
 
#define SKW_TXQ_HIGH_THRESHOLD     768
#define SKW_TXQ_LOW_THRESHOLD      512
 
#define SKW_TX_WAIT_TIME 1000000
 
#define SKW_TX_VRING_SIZE    128
 
struct skw_tx_vring {
   struct page *page;
   int tx_bytes;
   struct vring vr;
   void *queue_mem;  // 新增:记录vring内存块指针
 
   struct scatterlist *sgl_dat;
   spinlock_t lock;
 
   atomic_t set, write;
};
 
enum SKW_TX_RUNNING_STATE {
   SKW_TX_RUNNING_EXIT,
   SKW_TX_RUNNING_RESTART,
   SKW_TX_RUNNING_GO,
};
 
struct skw_tx_desc_hdr {
   /* pading bytes for gap */
   u16 padding_gap:2;
   u16 inst:2;
   u16 tid:4;
   u16 peer_lut:5;
 
   /* frame_type:
    * 0: ethernet frame
    * 1: 80211 frame
    */
   u16 frame_type:1;
   u16 encry_dis:1;
 
   /* rate: 0: auto, 1: sw config */
   u16 rate:1;
 
   u16 msdu_len:12;
   u16 lmac_id:2;
   u16 rsv:2;
   u16 eth_type;
 
   /* pading for address align */
   u8 gap[0];
} __packed;
 
struct skw_tx_desc_conf {
   u16 l4_hdr_offset:10;
   u16 csum:1;
 
   /* ip_prot: 0: UDP, 1: TCP */
   u16 ip_prot:1;
   u16 rsv:4;
} __packed;
 
struct skw_tx_cb {
   u8 ret:1;
   u8 recycle:1;
   u8 lmac_id;
   u8 peer_idx;
   u8 tx_retry;
   u16 skb_native_len;
   dma_addr_t skb_data_pa;
   struct skw_edma_elem e;
};
 
static inline void
skw_set_tx_desc_eth_type(struct skw_tx_desc_hdr *desc_hdr, u16 proto)
{
   desc_hdr->eth_type = proto;
}
 
static inline int skw_tx_allowed(unsigned long flags)
{
   unsigned long mask = BIT(SKW_FLAG_FW_ASSERT) |
                BIT(SKW_FLAG_BLOCK_TX) |
                BIT(SKW_FLAG_MP_MODE) |
                BIT(SKW_FLAG_FW_THERMAL) |
                BIT(SKW_FLAG_FW_MAC_RECOVERY);
 
   return !(mask & flags);
}
 
static inline int skw_cmd_tx_allowed(unsigned long flags)
{
   clear_bit(SKW_FLAG_FW_THERMAL, &flags);
 
   return skw_tx_allowed(flags);
}
 
#ifdef CONFIG_SWT6621S_SKB_RECYCLE
void skw_recycle_skb_free(struct skw_core *skw, struct sk_buff *skb);
int skw_recycle_skb_copy(struct skw_core *skw, struct sk_buff *skb_recycle, struct sk_buff *skb);
struct sk_buff *skw_recycle_skb_get(struct skw_core *skw);
#endif
void skw_skb_kfree(struct skw_core *skw, struct sk_buff *skb);
 
int skw_pcie_cmd_xmit(struct skw_core *skw, void *data, int data_len);
int skw_pcie_xmit(struct skw_core *skw, int lmac_id, struct sk_buff_head *txq);
 
int skw_sdio_cmd_xmit(struct skw_core *skw, void *data, int data_len);
int skw_sdio_xmit(struct skw_core *skw, int lmac_id, struct sk_buff_head *txq);
 
int skw_usb_cmd_xmit(struct skw_core *skw, void *data, int data_len);
int skw_usb_xmit(struct skw_core *skw, int lmac_id, struct sk_buff_head *txq);
 
int skw_hw_xmit_init(struct skw_core *skw, int dma);
int skw_tx_init(struct skw_core *skw);
int skw_tx_deinit(struct skw_core *skw);
 
void skw_sdio_hdr_set(struct skw_core *skw, struct sk_buff *skb, int lmac_id);
int skw_vring_set(struct skw_core *skw, void *data, u16 len, int lmac_id);
u16 skw_vring_available_count(struct skw_tx_vring *tx_vring);
 
#endif