summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.h
blob: a541973d76379b9f6ca06d06b205b269e82119b8 (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
// SPDX-License-Identifier: GPL-2.0-or-later
/**
 * aicwf_txrxif.h
 *
 * bus function declarations
 *
 * Copyright (C) AICSemi 2018-2020
 */

#ifndef _AICWF_TXRXIF_H_
#define _AICWF_TXRXIF_H_

#include <linux/skbuff.h>
#include <linux/sched.h>
#include "ipc_shared.h"
#include "aicwf_rx_prealloc.h"
#ifdef AICWF_SDIO_SUPPORT
#include "aicwf_sdio.h"
#else
#include "aicwf_usb.h"
#endif

#define CMD_BUF_MAX                 1536
#define DATA_BUF_MAX                2048
#define TXPKT_BLOCKSIZE             512
#define MAX_AGGR_TXPKT_LEN          (1536*64)
#define CMD_TX_TIMEOUT              5000
#define TX_ALIGNMENT                4

#ifdef CONFIG_USB_TX_AGGR
#define MAX_USB_AGGR_TXPKT_LEN          (1536*15)
#endif

#define RX_HWHRD_LEN                60 //58->60 word allined
#define CCMP_OR_WEP_INFO            8
#define MAX_RXQLEN                  2000
#define RX_ALIGNMENT                4

#define DEBUG_ERROR_LEVEL           0
#define DEBUG_DEBUG_LEVEL           1
#define DEBUG_INFO_LEVEL            2

#define DBG_LEVEL                   DEBUG_DEBUG_LEVEL

#define txrx_err(fmt, ...)          pr_err("txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#define sdio_err(fmt, ...)          pr_err("sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#define usb_err(fmt, ...)           pr_err("usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL
#define txrx_dbg(fmt, ...)          printk("txrx: " fmt, ##__VA_ARGS__)
#define sdio_dbg(fmt, ...)          printk("aicsdio: " fmt, ##__VA_ARGS__)
#define usb_dbg(fmt, ...)           printk("aicusb: " fmt, ##__VA_ARGS__)
#else
#define txrx_dbg(fmt, ...)
#define sdio_dbg(fmt, ...)
#define usb_dbg(fmt, ...)
#endif
#if DBG_LEVEL >= DEBUG_INFO_LEVEL
#define txrx_info(fmt, ...)         printk("aicsdio: " fmt, ##__VA_ARGS__)
#define sdio_info(fmt, ...)         printk("aicsdio: " fmt, ##__VA_ARGS__)
#define usb_info(fmt, ...)          printk("aicusb: " fmt, ##__VA_ARGS__)
#else
#define txrx_info(fmt, ...)
#define sdio_info(fmt, ...)
#define usb_info(fmt, ...)
#endif

enum aicwf_bus_state {
    BUS_DOWN_ST,
    BUS_UP_ST
};

struct aicwf_bus_ops {
    int (*start) (struct device * dev);
    void (*stop) (struct device * dev);
    int (*txdata) (struct device * dev, struct sk_buff * skb);
    int (*txmsg) (struct device * dev, u8 * msg, uint len);
};

struct frame_queue {
    u16              num_prio;
    u16              hi_prio;
    u16              qmax;      /* max number of queued frames */
    u16              qcnt;
    struct sk_buff_head queuelist[8];
};

#ifdef CONFIG_PREALLOC_RX_SKB
struct rx_frame_queue {
    u16              qmax;      /* max number of queued frames */
    u16              qcnt;
    struct list_head queuelist;
};
#endif

struct aicwf_bus {
    union {
        struct aic_sdio_dev *sdio;
        struct aic_usb_dev *usb;
    } bus_priv;
    struct device *dev;
    struct aicwf_bus_ops *ops;
    enum aicwf_bus_state state;
    u8 *cmd_buf;
    struct completion bustx_trgg;
    struct completion busrx_trgg;
#ifdef CONFIG_USB_MSG_IN_EP
	struct completion msg_busrx_trgg;
#endif

    struct task_struct *bustx_thread;
    struct task_struct *busrx_thread;
#ifdef CONFIG_USB_MSG_IN_EP
	struct task_struct *msg_busrx_thread;
#endif

};

struct aicwf_tx_priv {
#ifdef AICWF_SDIO_SUPPORT
    struct aic_sdio_dev *sdiodev;
    int fw_avail_bufcnt;
    //for cmd tx
    u8 *cmd_buf;
    uint cmd_len;
    bool cmd_txstate;
    bool cmd_tx_succ;
    struct semaphore cmd_txsema;
    wait_queue_head_t cmd_txdone_wait;
    //for data tx
    atomic_t tx_pktcnt;

    struct frame_queue txq;
    spinlock_t txqlock;
    struct semaphore txctl_sema;
#endif
#ifdef AICWF_USB_SUPPORT
    struct aic_usb_dev *usbdev;
#ifdef CONFIG_USB_TX_AGGR
    int fw_avail_bufcnt;

    //for data tx
    atomic_t tx_pktcnt;

    struct frame_queue txq;
    spinlock_t txqlock;
    spinlock_t txdlock;
#endif
#endif//AICWF_USB_SUPPORT
    struct sk_buff *aggr_buf;
    atomic_t aggr_count;
    u8 *head;
    u8 *tail;
};


#ifdef AICWF_RX_REORDER
#define MAX_REORD_RXFRAME       250
#define REORDER_UPDATE_TIME     500//50
#define AICWF_REORDER_WINSIZE   64
//SN_LESS(a, b) a-b<0 is ture
#define SN_LESS(a, b)           (((a-b)&0x800)!=0)
#define SN_EQUAL(a, b)          (a == b)

struct reord_ctrl {
    struct aicwf_rx_priv *rx_priv;
    u8 enable;
    u16 ind_sn;
    u8 wsize_b;
    spinlock_t reord_list_lock;
    struct list_head reord_list;
    struct timer_list reord_timer;
    struct work_struct reord_timer_work;
};

struct reord_ctrl_info {
    u8 mac_addr[6];
    struct reord_ctrl preorder_ctrl[8];
    struct list_head list;
};

struct recv_msdu {
     struct sk_buff  *pkt;
     u8 tid;
	 u8 forward;
     u16 seq_num;
     uint len;
     u8 *rx_data;
     //for pending rx reorder list
    struct list_head reord_pending_list;
    //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue
    struct list_head rxframe_list;
    struct reord_ctrl *preorder_ctrl;
};
#endif

struct aicwf_rx_priv {
#ifdef AICWF_SDIO_SUPPORT
    struct aic_sdio_dev *sdiodev;
#endif
#ifdef AICWF_USB_SUPPORT
    struct aic_usb_dev *usbdev;
#endif

    void *rwnx_vif;
    atomic_t rx_cnt;
    u32 data_len;
    spinlock_t rxqlock;
#ifdef CONFIG_PREALLOC_RX_SKB
	struct rx_frame_queue rxq;
#else
	struct frame_queue rxq;
#endif

#ifdef CONFIG_USB_MSG_IN_EP
	atomic_t msg_rx_cnt;
	spinlock_t msg_rxqlock;
	struct frame_queue msg_rxq;
#endif


#ifdef AICWF_RX_REORDER
    spinlock_t freeq_lock;
    struct list_head rxframes_freequeue;
    struct list_head stas_reord_list;
    spinlock_t stas_reord_lock;
    struct recv_msdu *recv_frames;
#endif

#ifdef CONFIG_PREALLOC_RX_SKB
	spinlock_t rxbuff_lock;
#endif

};

static inline int aicwf_bus_start(struct aicwf_bus *bus)
{
    return bus->ops->start(bus->dev);
}

static inline void aicwf_bus_stop(struct aicwf_bus *bus)
{
    bus->ops->stop(bus->dev);
}

static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb)
{
    return bus->ops->txdata(bus->dev, skb);
}

static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len)
{
    return bus->ops->txmsg(bus->dev, msg, len);
}

static inline void aicwf_sched_timeout(u32 millisec)
{
    ulong timeout = 0, expires = 0;
    expires = jiffies + msecs_to_jiffies(millisec);
    timeout = millisec;

    while (timeout) {
        timeout = schedule_timeout(timeout);
        if (time_after(jiffies, expires))
            break;
    }
}

int aicwf_bus_init(uint bus_hdrlen, struct device *dev);
void aicwf_bus_deinit(struct device *dev);
void aicwf_tx_deinit(struct aicwf_tx_priv* tx_priv);
void aicwf_rx_deinit(struct aicwf_rx_priv* rx_priv);
struct aicwf_tx_priv* aicwf_tx_init(void *arg);
struct aicwf_rx_priv* aicwf_rx_init(void *arg);
void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len);
void aicwf_frame_queue_flush(struct frame_queue *pq);
bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio);
bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt);
bool aicwf_is_framequeue_empty(struct frame_queue *pq);
void aicwf_frame_tx(void *dev, struct sk_buff *skb);
void aicwf_dev_skb_free(struct sk_buff *skb);
struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq);
struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out);
#ifdef CONFIG_PREALLOC_RX_SKB
void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv);
void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len);
void rxbuff_free(struct rx_buff *rxbuff);
struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq);
bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt);
extern struct aicwf_rx_buff_list aic_rx_buff_list;
#endif

#endif /* _AICWF_TXRXIF_H_ */