hc
2023-11-06 15ade055295d13f95d49e3d99b09f3bbfb4a43e7
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
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef WCN_USB_H
#define WCN_USB_H
 
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
#include <linux/kthread.h>
#include <linux/notifier.h>
#include <wcn_bus.h>
#include <marlin_platform.h>
 
#define wcn_usb_info(fmt, args...) \
   pr_info("wcn_usb info " fmt, ## args)
 
#define wcn_usb_info_ratelimited(fmt, args...) \
   printk_ratelimited("wcn_usb info " fmt, ## args)
 
#define wcn_usb_debug(fmt, args...) \
   pr_debug("wcn_usb debug " fmt, ## args)
 
#define wcn_usb_err(fmt, args...) \
   pr_err("wcn_usb err " fmt, ## args)
 
char get_wcn_usb_print_switch(void);
#define wcn_usb_print(mask, fmt, args...)    \
   do {                    \
       if (get_wcn_usb_print_switch() & mask)\
           pr_info("wcn_usb info " fmt, ## args); \
   } while (0)
#define rx_tx_info 0x08
#define packet_info 0x04
#define mbuf_info 0x02
#define extern_info 0x01
 
#define wcn_usb_print_packet(packet) \
   wcn_usb_print(packet_info, \
           "%s+%d packet %p ->chn %d ->urb %p\n", \
           __func__, __LINE__, packet, \
       packet->ep ? packet->ep->channel : -1, packet->urb)
 
/**
 * struct wcn_usb_store_intf - The object inherited from struct usb_interface.
 * @interface: We inherited from it.
 * @udev: interface->usb_device.
 * @lock: keep { num_users change_flags is a atomic }.
 * @num_users: How many object need this intf now.
 * @flags_lock: keep { change_flags } only one can access;
 * @change_flag: Is this intf need be changed? (if it is, don't add num_users!)
 */
struct wcn_usb_intf {
   struct usb_interface *interface;
   struct usb_device *udev;
   spinlock_t lock;
   char num_users;
   struct mutex flag_lock;
   char change_flag;
   wait_queue_head_t wait_user;
};
 
/**
 * struct wcn_usb_ep - The object descrise a endpoint for wcn usb.
 * @intf_lock: keep { intf intf->users } is a atomic.
 * @intf: This endpoint must belong to a interface.
 * @epNum: This endpoint's index in interface's cur_altsetting->endpoint[]
 *    that it belong to.
 * @submitted: for retract urb;
 */
struct wcn_usb_ep {
   int channel;
   spinlock_t intf_lock;
   struct wcn_usb_intf *intf;
   __u8 numEp;
   struct usb_anchor submitted;
   spinlock_t submit_lock;
};
 
/**
 * struct wcn_usb_packet - The object for broke talk with io.
 * @urb: from usb_alloc_urb. user don't touch it!
 * @ep: record ep point.
 * @is_usb_anchor: to indicate this buf is alloc with usb_alloc_coherent.
 * @callback: be called after the packet transfer ok.
 * @pdata: to callback.
 *
 * NOTE: user don't touch any feild in this struct, unless you sure it is right
 * that what you do!
 */
struct wcn_usb_packet {
   struct urb *urb;
   struct wcn_usb_ep *ep;
   bool is_usb_anchor;
   void (*callback)(struct wcn_usb_packet *packet);
   void *pdata;
};
 
struct wcn_usb_rx_tx {
   struct wcn_usb_packet *packet;
   struct mbuf_t *head;
   struct mbuf_t *tail;
   int num;
   int channel;
   int packet_status;
   struct list_head list;
};
 
#define wcn_usb_print_rx_tx(rx_tx)        \
   wcn_usb_print(rx_tx_info, "%s+%d rx_tx %p ->packet %p ->head"\
       " %p ->tail %p ->num %d ->channel %d ->packet_status %d\n", \
       __func__, __LINE__, rx_tx, rx_tx->packet, \
       rx_tx->head, rx_tx->tail, rx_tx->num, \
       rx_tx->channel, rx_tx->packet_status)
 
struct wcn_usb_notifier {
   struct notifier_block nb;
   void (*cb)(void *);
   void *data;
   unsigned long event;
};
 
struct wcn_usb_work_data {
   struct task_struct    *wcn_usb_thread;
   wait_queue_head_t    wait_mbuf;
   wait_queue_head_t    work_completion;
   struct mutex        channel_lock;
   spinlock_t        lock;
   struct list_head    rx_tx_head;
   int            channel;
   int            report_num;
   int            report_num_last;
   int            transfer_remains;
   int            goon;
   struct completion    callback_complete;
   struct wcn_usb_notifier    *wn;
};
 
 
struct wcn_usb_work_data *wcn_usb_store_get_channel_info(int channel);
int wcn_usb_store_register_channel_info(int channel, void *info);
struct wcn_usb_ep *wcn_usb_store_get_epFRchn(int channel);
int wcn_usb_store_init(void);
void wcn_usb_store_delet(void);
__u8 wcn_usb_store_chn2addr(int channel);
struct usb_endpoint_descriptor *wcn_usb_intf2endpoint(struct wcn_usb_intf *intf,
                   __u8 numEp);
typedef int (*ep_handle_cb)(struct wcn_usb_ep *ep, void *pdata);
int wcn_usb_store_travel_ep(ep_handle_cb cb, void *pdata);
 
int wcn_usb_packet_get_status(struct wcn_usb_packet *packet);
void wcn_usb_ep_stop(struct wcn_usb_ep *ep);
void wcn_usb_packet_free(struct wcn_usb_packet *packet);
void wcn_usb_io_delet(void);
int wcn_usb_io_init(void);
int wcn_usb_packet_set_buf(struct wcn_usb_packet *packet,
               void *buf, ssize_t buf_size,  gfp_t mem_flags);
void wcn_usb_packet_free_buf(struct wcn_usb_packet *packet);
int wcn_usb_packet_set_sg(struct wcn_usb_packet *packet, struct scatterlist *sg,
               int num_sgs, unsigned int buf_len);
struct wcn_usb_packet *wcn_usb_alloc_packet(gfp_t mem_flags);
struct scatterlist *wcn_usb_packet_pop_sg(struct wcn_usb_packet *packet,
                       int *num_sgs);
int wcn_usb_msg(struct wcn_usb_ep *ep, void *data, int len,
       int *actual_length, int timeout);
int wcn_usb_packet_submit(struct wcn_usb_packet *packet,
       void (*callback)(struct wcn_usb_packet *packet),
       void *pdata, gfp_t mem_flags);
int wcn_usb_ep_can_dma(struct wcn_usb_ep *ep);
void wcn_usb_packet_interval(struct wcn_usb_packet *packet, int interval);
unsigned int wcn_usb_packet_recv_len(struct wcn_usb_packet *packet);
int wcn_usb_ep_set(struct wcn_usb_ep *ep, int setting_id);
void wcn_usb_wait_channel_stop(int chn);
int wcn_usb_packet_bind(struct wcn_usb_packet *packet, struct wcn_usb_ep *ep,
       gfp_t mem_flags);
void wcn_usb_packet_clean(struct wcn_usb_packet *packet);
int wcn_usb_packet_set_setup_packet(struct wcn_usb_packet *packet,
                   struct usb_ctrlrequest *setup_packet);
struct usb_ctrlrequest *wcn_usb_packet_pop_setup_packet(
                       struct wcn_usb_packet *packet);
 
#define wcn_usb_packet_get_buf(packet) \
   (packet->buf)
#define wcn_usb_ep_init(ep, id) \
   do { \
       ep->channel = id; \
       ep->intf = NULL; \
       ep->numEp = -1; \
       spin_lock_init(&ep->intf_lock); \
       init_usb_anchor(&ep->submitted); \
       spin_lock_init(&ep->submit_lock); \
   } while (0)
 
#if 0
#define wcn_usb_work_data_init(work_data, id) \
   do { \
       work_data->channel = id; \
       mutex_init(&work_data->channel_lock); \
       spin_lock_init(&work_data->lock); \
       init_waitqueue_head(&work_data->wait_mbuf); \
       INIT_WORK(&work_data->wcn_usb_work, wcn_usb_work_func); \
       init_waitqueue_head(&work_data->work_completion); \
       init_completion(&work_data->callback_complete);\
   } while (0)
#endif
 
void wcn_usb_work_data_init(struct wcn_usb_work_data *work_data, int id);
 
/* follow macro call wcn_usb_intf2endpoint
 * So we need hold intf, before we call them
 */
#define wcn_usb_ep_address(ep) \
       (wcn_usb_intf2endpoint(ep->intf, ep->numEp)->bEndpointAddress)
#define wcn_usb_ep_interval(ep) \
       (wcn_usb_intf2endpoint(ep->intf, ep->numEp)->bInterval)
#define wcn_usb_ep_packet_max(ep) \
       usb_endpoint_maxp(wcn_usb_intf2endpoint(ep->intf, ep->numEp))
#define wcn_usb_ep_is_isoc(ep) \
   usb_endpoint_xfer_isoc(wcn_usb_intf2endpoint(ep->intf, ep->numEp))
#define wcn_usb_ep_is_int(ep) \
   usb_endpoint_xfer_int(wcn_usb_intf2endpoint(ep->intf, ep->numEp))
#define wcn_usb_ep_is_ctrl(ep) \
   usb_endpoint_xfer_control(wcn_usb_intf2endpoint(ep->intf, ep->numEp))
#define wcn_usb_ep_is_bulk(ep) \
   usb_endpoint_xfer_bulk(wcn_usb_intf2endpoint(ep->intf, ep->numEp))
#define wcn_usb_ep_no_sg_constraint(ep) \
       (ep->intf->udev->bus->no_sg_constraint)
#define wcn_usb_ep_dir(ep) \
   usb_endpoint_dir_in(wcn_usb_intf2endpoint(ep->intf, ep->numEp))
 
#define wcn_usb_packet_get_pdata(packet) \
       (packet->pdata)
 
#define wcn_usb_ep_is_stop(ep) \
   usb_anchor_empty(&ep->submitted)
 
#define wcn_usb_packet_setup_packet(packet, setup_packet) \
       (packet->urb->setup_packet = setup_packet)
 
#define wcn_usb_intf_epNum(intf) \
   intf->interface->cur_altsetting->desc.bNumEndpoints
 
/* @head: list's head
 * @num: list's num
 * @pos: current node, if eq null then we done all list with success. if eq is
 *    not null, then it point the node that error one.
 * @posN: current node's index, if pos eq null then it eq num.
 */
#define mbuf_list_iter(head, num, pos, posN) \
   for (pos = head, posN = 0; posN < num && pos; posN++, pos = pos->next)
 
int  wcn_usb_push_list_tx(int chn, struct mbuf_t *head,
       struct mbuf_t *tail, int num);
int wcn_usb_push_list_rx(int chn, struct mbuf_t *head,
       struct mbuf_t *tail, int num);
void wcn_usb_begin_poll_rx(int chn);
void wcn_usb_mbuf_free_notif(int chn);
int wcn_usb_list_alloc(int chn, struct mbuf_t **head,
       struct mbuf_t **tail, int *num);
int wcn_usb_list_free(int chn, struct mbuf_t *head,
       struct mbuf_t *tail, int num);
int wcn_usb_rx_tx_pool_init(void);
void wcn_usb_rx_tx_pool_deinit(void);
 
unsigned long long wcn_usb_get_rx_tx_cnt(void);
 
enum wcn_usb_event {
   interface_plug_base,
   interface_0_plug = interface_plug_base,
   interface_1_plug,
   interface_2_plug,
   dev_plug_fully,
 
   interface_unplug_base,
   interface_0_unplug = interface_unplug_base,
   interface_1_unplug,
   interface_2_unplug,
   dev_unplug_fully,
 
   download_over,
   cp_ready,
   pwr_on,
   pwr_off,
   pwr_state,
   error_happen,
   error_clean,
};
 
 
int wcn_usb_apostle_begin(int chn);
int wcn_usb_store_addr2chn(__u8 epAddress);
 
int wcn_usb_packet_is_freed(struct wcn_usb_packet *packet);
void *wcn_usb_packet_pop_buf(struct wcn_usb_packet *packet);
void wcn_usb_init_copy_men(void);
 
void channel_debug_mbuf_from_user(int chn, int num);
void channel_debug_mbuf_to_user(int chn, int num);
void channel_debug_mbuf_free(int chn, int num);
void channel_debug_mbuf_alloc(int chn, int num);
void channel_debug_rx_tx_from_controller(int chn, int num);
void channel_debug_rx_tx_to_controller(int chn, int num);
void channel_debug_rx_tx_free(int chn, int num);
void channel_debug_rx_tx_alloc(int chn, int num);
void channel_debug_to_accept(int chn, int num);
void channel_debug_report_num(int chn, int num);
void channel_debug_kzalloc(int times);
void channel_debug_net_free(int times);
void channel_debug_net_malloc(int times);
void channel_debug_free_big_men(int chn);
void channel_debug_alloc_big_men(int chn);
#if 0
void channel_debug_push_list_no_null(int times);
#endif
void channel_debug_packet_no_full(int times);
void channel_debug_free_with_accient(int times);
void channel_debug_mbuf_10(int times);
void channel_debug_mbuf_4(int times);
void channel_debug_mbuf_1(int times);
void channel_debug_mbuf_8(int times);
void channel_debug_interrupt_callback(int times);
void channel_debug_cp_num(int times);
int wcn_usb_chnmg_init(void);
 
 
int wcn_usb_state_sent_event(enum wcn_usb_event event);
int wcn_usb_state_register(struct notifier_block *nb);
int wcn_usb_state_unregister(struct notifier_block *nb);
int wcn_usb_state_get(enum wcn_usb_event event);
void wcn_usb_state_clear(enum wcn_usb_event event);
 
/* for test dump */
unsigned int marlin_get_wcn_chipid(void);
int marlin_dump_from_romcode_usb(unsigned int addr, void *buf, int len);
int marlin_get_version(void);
int marlin_connet(void);
#endif