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#ifndef __HWAHC_INTERNAL_H__
81#define __HWAHC_INTERNAL_H__
82
83#include <linux/completion.h>
84#include <linux/usb.h>
85#include <linux/mutex.h>
86#include <linux/spinlock.h>
87#include <linux/uwb.h>
88#include <linux/usb/wusb.h>
89#include <linux/usb/wusb-wa.h>
90
91struct wusbhc;
92struct wahc;
93extern void wa_urb_enqueue_run(struct work_struct *ws);
94extern void wa_process_errored_transfers_run(struct work_struct *ws);
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113struct wa_rpipe {
114 struct kref refcnt;
115 struct usb_rpipe_descriptor descr;
116 struct usb_host_endpoint *ep;
117 struct wahc *wa;
118 spinlock_t seg_lock;
119 struct list_head seg_list;
120 struct list_head list_node;
121 atomic_t segs_available;
122 u8 buffer[1];
123};
124
125
126enum wa_dti_state {
127 WA_DTI_TRANSFER_RESULT_PENDING,
128 WA_DTI_ISOC_PACKET_STATUS_PENDING,
129 WA_DTI_BUF_IN_DATA_PENDING
130};
131
132enum wa_quirks {
133
134
135
136
137 WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC = 0x01,
138
139
140
141
142 WUSB_QUIRK_ALEREON_HWA_DISABLE_XFER_NOTIFICATIONS = 0x02,
143};
144
145enum wa_vendor_specific_requests {
146 WA_REQ_ALEREON_DISABLE_XFER_NOTIFICATIONS = 0x4C,
147 WA_REQ_ALEREON_FEATURE_SET = 0x01,
148 WA_REQ_ALEREON_FEATURE_CLEAR = 0x00,
149};
150
151#define WA_MAX_BUF_IN_URBS 4
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
186struct wahc {
187 struct usb_device *usb_dev;
188 struct usb_interface *usb_iface;
189
190
191 union {
192 struct wusbhc *wusb;
193 struct dwahc *dwa;
194 };
195
196 const struct usb_endpoint_descriptor *dto_epd, *dti_epd;
197 const struct usb_wa_descriptor *wa_descr;
198
199 struct urb *nep_urb;
200 struct edc nep_edc;
201 void *nep_buffer;
202 size_t nep_buffer_size;
203
204 atomic_t notifs_queued;
205
206 u16 rpipes;
207 unsigned long *rpipe_bm;
208 struct list_head rpipe_delayed_list;
209 spinlock_t rpipe_lock;
210 struct mutex rpipe_mutex;
211
212
213
214
215
216
217
218 enum wa_dti_state dti_state;
219 u32 dti_isoc_xfer_in_progress;
220 u8 dti_isoc_xfer_seg;
221 struct urb *dti_urb;
222
223 struct urb buf_in_urbs[WA_MAX_BUF_IN_URBS];
224 int active_buf_in_urbs;
225 struct edc dti_edc;
226 void *dti_buf;
227 size_t dti_buf_size;
228
229 unsigned long dto_in_use;
230
231 s32 status;
232
233 struct list_head xfer_list;
234 struct list_head xfer_delayed_list;
235 struct list_head xfer_errored_list;
236
237
238
239
240 spinlock_t xfer_list_lock;
241 struct work_struct xfer_enqueue_work;
242 struct work_struct xfer_error_work;
243 atomic_t xfer_id_count;
244
245 kernel_ulong_t quirks;
246};
247
248
249extern int wa_create(struct wahc *wa, struct usb_interface *iface,
250 kernel_ulong_t);
251extern void __wa_destroy(struct wahc *wa);
252extern int wa_dti_start(struct wahc *wa);
253void wa_reset_all(struct wahc *wa);
254
255
256
257enum {
258
259
260 HWAHC_EPROTO_MAX = 16,
261
262 HWAHC_EPROTO_PERIOD = 4 * HZ,
263};
264
265
266
267extern int wa_nep_create(struct wahc *, struct usb_interface *);
268extern void wa_nep_destroy(struct wahc *);
269
270static inline int wa_nep_arm(struct wahc *wa, gfp_t gfp_mask)
271{
272 struct urb *urb = wa->nep_urb;
273 urb->transfer_buffer = wa->nep_buffer;
274 urb->transfer_buffer_length = wa->nep_buffer_size;
275 return usb_submit_urb(urb, gfp_mask);
276}
277
278static inline void wa_nep_disarm(struct wahc *wa)
279{
280 usb_kill_urb(wa->nep_urb);
281}
282
283
284
285static inline void wa_rpipe_init(struct wahc *wa)
286{
287 INIT_LIST_HEAD(&wa->rpipe_delayed_list);
288 spin_lock_init(&wa->rpipe_lock);
289 mutex_init(&wa->rpipe_mutex);
290}
291
292static inline void wa_init(struct wahc *wa)
293{
294 int index;
295
296 edc_init(&wa->nep_edc);
297 atomic_set(&wa->notifs_queued, 0);
298 wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
299 wa_rpipe_init(wa);
300 edc_init(&wa->dti_edc);
301 INIT_LIST_HEAD(&wa->xfer_list);
302 INIT_LIST_HEAD(&wa->xfer_delayed_list);
303 INIT_LIST_HEAD(&wa->xfer_errored_list);
304 spin_lock_init(&wa->xfer_list_lock);
305 INIT_WORK(&wa->xfer_enqueue_work, wa_urb_enqueue_run);
306 INIT_WORK(&wa->xfer_error_work, wa_process_errored_transfers_run);
307 wa->dto_in_use = 0;
308 atomic_set(&wa->xfer_id_count, 1);
309
310 for (index = 0; index < WA_MAX_BUF_IN_URBS; ++index)
311 usb_init_urb(&(wa->buf_in_urbs[index]));
312 wa->active_buf_in_urbs = 0;
313}
314
315
316
317
318
319
320struct wa_xfer;
321extern void rpipe_destroy(struct kref *_rpipe);
322static inline
323void __rpipe_get(struct wa_rpipe *rpipe)
324{
325 kref_get(&rpipe->refcnt);
326}
327extern int rpipe_get_by_ep(struct wahc *, struct usb_host_endpoint *,
328 struct urb *, gfp_t);
329static inline void rpipe_put(struct wa_rpipe *rpipe)
330{
331 kref_put(&rpipe->refcnt, rpipe_destroy);
332
333}
334extern void rpipe_ep_disable(struct wahc *, struct usb_host_endpoint *);
335extern void rpipe_clear_feature_stalled(struct wahc *,
336 struct usb_host_endpoint *);
337extern int wa_rpipes_create(struct wahc *);
338extern void wa_rpipes_destroy(struct wahc *);
339static inline void rpipe_avail_dec(struct wa_rpipe *rpipe)
340{
341 atomic_dec(&rpipe->segs_available);
342}
343
344
345
346
347static inline int rpipe_avail_inc(struct wa_rpipe *rpipe)
348{
349 return atomic_inc_return(&rpipe->segs_available) > 0
350 && !list_empty(&rpipe->seg_list);
351}
352
353
354
355extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *,
356 struct urb *, gfp_t);
357extern int wa_urb_dequeue(struct wahc *, struct urb *, int);
358extern void wa_handle_notif_xfer(struct wahc *, struct wa_notif_hdr *);
359
360
361
362
363
364
365
366
367
368
369
370
371
372static inline struct wahc *wa_get(struct wahc *wa)
373{
374 usb_get_intf(wa->usb_iface);
375 return wa;
376}
377
378static inline void wa_put(struct wahc *wa)
379{
380 usb_put_intf(wa->usb_iface);
381}
382
383
384static inline int __wa_feature(struct wahc *wa, unsigned op, u16 feature)
385{
386 return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0),
387 op ? USB_REQ_SET_FEATURE : USB_REQ_CLEAR_FEATURE,
388 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
389 feature,
390 wa->usb_iface->cur_altsetting->desc.bInterfaceNumber,
391 NULL, 0, USB_CTRL_SET_TIMEOUT);
392}
393
394
395static inline int __wa_set_feature(struct wahc *wa, u16 feature)
396{
397 return __wa_feature(wa, 1, feature);
398}
399
400
401static inline int __wa_clear_feature(struct wahc *wa, u16 feature)
402{
403 return __wa_feature(wa, 0, feature);
404}
405
406
407
408
409
410
411
412
413
414
415
416static inline
417s32 __wa_get_status(struct wahc *wa)
418{
419 s32 result;
420 result = usb_control_msg(
421 wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0),
422 USB_REQ_GET_STATUS,
423 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
424 0, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber,
425 &wa->status, sizeof(wa->status), USB_CTRL_GET_TIMEOUT);
426 if (result >= 0)
427 result = wa->status;
428 return result;
429}
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444static inline s32 __wa_wait_status(struct wahc *wa, u32 mask, u32 value)
445{
446 s32 result;
447 unsigned loops = 10;
448 do {
449 msleep(50);
450 result = __wa_get_status(wa);
451 if ((result & mask) == value)
452 break;
453 if (loops-- == 0) {
454 result = -ETIMEDOUT;
455 break;
456 }
457 } while (result >= 0);
458 return result;
459}
460
461
462
463static inline int __wa_stop(struct wahc *wa)
464{
465 int result;
466 struct device *dev = &wa->usb_iface->dev;
467
468 result = __wa_clear_feature(wa, WA_ENABLE);
469 if (result < 0 && result != -ENODEV) {
470 dev_err(dev, "error commanding HC to stop: %d\n", result);
471 goto out;
472 }
473 result = __wa_wait_status(wa, WA_ENABLE, 0);
474 if (result < 0 && result != -ENODEV)
475 dev_err(dev, "error waiting for HC to stop: %d\n", result);
476out:
477 return 0;
478}
479
480
481#endif
482