|
@@ -35,10 +35,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
35
|
35
|
*
|
36
|
36
|
*/
|
37
|
37
|
|
38
|
|
-/** Refill profiler */
|
39
|
|
-static struct profiler ecm_refill_profiler __profiler =
|
40
|
|
- { .name = "ecm.refill" };
|
41
|
|
-
|
42
|
38
|
/** Interrupt completion profiler */
|
43
|
39
|
static struct profiler ecm_intr_profiler __profiler =
|
44
|
40
|
{ .name = "ecm.intr" };
|
|
@@ -114,68 +110,6 @@ int ecm_fetch_mac ( struct usb_device *usb,
|
114
|
110
|
return 0;
|
115
|
111
|
}
|
116
|
112
|
|
117
|
|
-/******************************************************************************
|
118
|
|
- *
|
119
|
|
- * Ring management
|
120
|
|
- *
|
121
|
|
- ******************************************************************************
|
122
|
|
- */
|
123
|
|
-
|
124
|
|
-/**
|
125
|
|
- * Transcribe receive ring name (for debugging)
|
126
|
|
- *
|
127
|
|
- * @v ecm CDC-ECM device
|
128
|
|
- * @v ring Receive ring
|
129
|
|
- * @ret name Receive ring name
|
130
|
|
- */
|
131
|
|
-static inline const char * ecm_rx_name ( struct ecm_device *ecm,
|
132
|
|
- struct ecm_rx_ring *ring ) {
|
133
|
|
- if ( ring == &ecm->intr ) {
|
134
|
|
- return "interrupt";
|
135
|
|
- } else if ( ring == &ecm->in ) {
|
136
|
|
- return "bulk IN";
|
137
|
|
- } else {
|
138
|
|
- return "UNKNOWN";
|
139
|
|
- }
|
140
|
|
-}
|
141
|
|
-
|
142
|
|
-/**
|
143
|
|
- * Refill receive ring
|
144
|
|
- *
|
145
|
|
- * @v ecm CDC-ECM device
|
146
|
|
- * @v ring Receive ring
|
147
|
|
- */
|
148
|
|
-static void ecm_rx_refill ( struct ecm_device *ecm, struct ecm_rx_ring *ring ) {
|
149
|
|
- struct net_device *netdev = ecm->netdev;
|
150
|
|
- struct io_buffer *iobuf;
|
151
|
|
- int rc;
|
152
|
|
-
|
153
|
|
- /* Refill ring */
|
154
|
|
- while ( ring->fill < ring->max ) {
|
155
|
|
-
|
156
|
|
- /* Profile refill */
|
157
|
|
- profile_start ( &ecm_refill_profiler );
|
158
|
|
-
|
159
|
|
- /* Allocate I/O buffer */
|
160
|
|
- iobuf = alloc_iob ( ring->mtu );
|
161
|
|
- if ( ! iobuf ) {
|
162
|
|
- /* Wait for next refill */
|
163
|
|
- break;
|
164
|
|
- }
|
165
|
|
- iob_put ( iobuf, ring->mtu );
|
166
|
|
-
|
167
|
|
- /* Enqueue I/O buffer */
|
168
|
|
- if ( ( rc = usb_stream ( &ring->ep, iobuf, 0 ) ) != 0 ) {
|
169
|
|
- netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
|
170
|
|
- break;
|
171
|
|
- }
|
172
|
|
-
|
173
|
|
- /* Increment fill level */
|
174
|
|
- ring->fill++;
|
175
|
|
- profile_stop ( &ecm_refill_profiler );
|
176
|
|
- }
|
177
|
|
-}
|
178
|
|
-
|
179
|
113
|
/******************************************************************************
|
180
|
114
|
*
|
181
|
115
|
* CDC-ECM communications interface
|
|
@@ -192,7 +126,7 @@ static void ecm_rx_refill ( struct ecm_device *ecm, struct ecm_rx_ring *ring ) {
|
192
|
126
|
*/
|
193
|
127
|
static void ecm_intr_complete ( struct usb_endpoint *ep,
|
194
|
128
|
struct io_buffer *iobuf, int rc ) {
|
195
|
|
- struct ecm_device *ecm = container_of ( ep, struct ecm_device, intr.ep);
|
|
129
|
+ struct ecm_device *ecm = container_of ( ep, struct ecm_device, intr );
|
196
|
130
|
struct net_device *netdev = ecm->netdev;
|
197
|
131
|
struct usb_setup_packet *message;
|
198
|
132
|
size_t len = iob_len ( iobuf );
|
|
@@ -200,10 +134,6 @@ static void ecm_intr_complete ( struct usb_endpoint *ep,
|
200
|
134
|
/* Profile completions */
|
201
|
135
|
profile_start ( &ecm_intr_profiler );
|
202
|
136
|
|
203
|
|
- /* Decrement fill level */
|
204
|
|
- assert ( ecm->intr.fill > 0 );
|
205
|
|
- ecm->intr.fill--;
|
206
|
|
-
|
207
|
137
|
/* Ignore packets cancelled when the endpoint closes */
|
208
|
138
|
if ( ! ep->open )
|
209
|
139
|
goto ignore;
|
|
@@ -220,6 +150,7 @@ static void ecm_intr_complete ( struct usb_endpoint *ep,
|
220
|
150
|
if ( len < sizeof ( *message ) ) {
|
221
|
151
|
DBGC ( ecm, "ECM %p underlength interrupt:\n", ecm );
|
222
|
152
|
DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
|
|
153
|
+ rc = -EINVAL;
|
223
|
154
|
goto error;
|
224
|
155
|
}
|
225
|
156
|
message = iobuf->data;
|
|
@@ -244,6 +175,7 @@ static void ecm_intr_complete ( struct usb_endpoint *ep,
|
244
|
175
|
default:
|
245
|
176
|
DBGC ( ecm, "ECM %p unrecognised interrupt:\n", ecm );
|
246
|
177
|
DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
|
|
178
|
+ rc = -ENOTSUP;
|
247
|
179
|
goto error;
|
248
|
180
|
}
|
249
|
181
|
|
|
@@ -275,19 +207,18 @@ static int ecm_comms_open ( struct ecm_device *ecm ) {
|
275
|
207
|
int rc;
|
276
|
208
|
|
277
|
209
|
/* Open interrupt endpoint */
|
278
|
|
- if ( ( rc = usb_endpoint_open ( &ecm->intr.ep ) ) != 0 ) {
|
|
210
|
+ if ( ( rc = usb_endpoint_open ( &ecm->intr ) ) != 0 ) {
|
279
|
211
|
DBGC ( ecm, "ECM %p could not open interrupt: %s\n",
|
280
|
212
|
ecm, strerror ( rc ) );
|
281
|
213
|
goto err_open;
|
282
|
214
|
}
|
283
|
215
|
|
284
|
|
- /* Refill interrupt ring */
|
285
|
|
- ecm_rx_refill ( ecm, &ecm->intr );
|
|
216
|
+ /* Refill interrupt endpoint */
|
|
217
|
+ usb_refill ( &ecm->intr );
|
286
|
218
|
|
287
|
219
|
return 0;
|
288
|
220
|
|
289
|
|
- usb_endpoint_close ( &ecm->intr.ep );
|
290
|
|
- assert ( ecm->intr.fill == 0 );
|
|
221
|
+ usb_endpoint_close ( &ecm->intr );
|
291
|
222
|
err_open:
|
292
|
223
|
return rc;
|
293
|
224
|
}
|
|
@@ -300,8 +231,7 @@ static int ecm_comms_open ( struct ecm_device *ecm ) {
|
300
|
231
|
static void ecm_comms_close ( struct ecm_device *ecm ) {
|
301
|
232
|
|
302
|
233
|
/* Close interrupt endpoint */
|
303
|
|
- usb_endpoint_close ( &ecm->intr.ep );
|
304
|
|
- assert ( ecm->intr.fill == 0 );
|
|
234
|
+ usb_endpoint_close ( &ecm->intr );
|
305
|
235
|
}
|
306
|
236
|
|
307
|
237
|
/******************************************************************************
|
|
@@ -320,16 +250,12 @@ static void ecm_comms_close ( struct ecm_device *ecm ) {
|
320
|
250
|
*/
|
321
|
251
|
static void ecm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
322
|
252
|
int rc ) {
|
323
|
|
- struct ecm_device *ecm = container_of ( ep, struct ecm_device, in.ep );
|
|
253
|
+ struct ecm_device *ecm = container_of ( ep, struct ecm_device, in );
|
324
|
254
|
struct net_device *netdev = ecm->netdev;
|
325
|
255
|
|
326
|
256
|
/* Profile receive completions */
|
327
|
257
|
profile_start ( &ecm_in_profiler );
|
328
|
258
|
|
329
|
|
- /* Decrement fill level */
|
330
|
|
- assert ( ecm->in.fill > 0 );
|
331
|
|
- ecm->in.fill--;
|
332
|
|
-
|
333
|
259
|
/* Ignore packets cancelled when the endpoint closes */
|
334
|
260
|
if ( ! ep->open )
|
335
|
261
|
goto ignore;
|
|
@@ -373,7 +299,7 @@ static int ecm_out_transmit ( struct ecm_device *ecm,
|
373
|
299
|
profile_start ( &ecm_out_profiler );
|
374
|
300
|
|
375
|
301
|
/* Enqueue I/O buffer */
|
376
|
|
- if ( ( rc = usb_stream ( &ecm->out.ep, iobuf, 1 ) ) != 0 )
|
|
302
|
+ if ( ( rc = usb_stream ( &ecm->out, iobuf, 1 ) ) != 0 )
|
377
|
303
|
return rc;
|
378
|
304
|
|
379
|
305
|
profile_stop ( &ecm_out_profiler );
|
|
@@ -389,7 +315,7 @@ static int ecm_out_transmit ( struct ecm_device *ecm,
|
389
|
315
|
*/
|
390
|
316
|
static void ecm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
391
|
317
|
int rc ) {
|
392
|
|
- struct ecm_device *ecm = container_of ( ep, struct ecm_device, out.ep );
|
|
318
|
+ struct ecm_device *ecm = container_of ( ep, struct ecm_device, out );
|
393
|
319
|
struct net_device *netdev = ecm->netdev;
|
394
|
320
|
|
395
|
321
|
/* Report TX completion */
|
|
@@ -420,28 +346,27 @@ static int ecm_data_open ( struct ecm_device *ecm ) {
|
420
|
346
|
}
|
421
|
347
|
|
422
|
348
|
/* Open bulk IN endpoint */
|
423
|
|
- if ( ( rc = usb_endpoint_open ( &ecm->in.ep ) ) != 0 ) {
|
|
349
|
+ if ( ( rc = usb_endpoint_open ( &ecm->in ) ) != 0 ) {
|
424
|
350
|
DBGC ( ecm, "ECM %p could not open bulk IN: %s\n",
|
425
|
351
|
ecm, strerror ( rc ) );
|
426
|
352
|
goto err_open_in;
|
427
|
353
|
}
|
428
|
354
|
|
429
|
355
|
/* Open bulk OUT endpoint */
|
430
|
|
- if ( ( rc = usb_endpoint_open ( &ecm->out.ep ) ) != 0 ) {
|
|
356
|
+ if ( ( rc = usb_endpoint_open ( &ecm->out ) ) != 0 ) {
|
431
|
357
|
DBGC ( ecm, "ECM %p could not open bulk OUT: %s\n",
|
432
|
358
|
ecm, strerror ( rc ) );
|
433
|
359
|
goto err_open_out;
|
434
|
360
|
}
|
435
|
361
|
|
436
|
|
- /* Refill bulk IN ring */
|
437
|
|
- ecm_rx_refill ( ecm, &ecm->in );
|
|
362
|
+ /* Refill bulk IN endpoint */
|
|
363
|
+ usb_refill ( &ecm->in );
|
438
|
364
|
|
439
|
365
|
return 0;
|
440
|
366
|
|
441
|
|
- usb_endpoint_close ( &ecm->out.ep );
|
|
367
|
+ usb_endpoint_close ( &ecm->out );
|
442
|
368
|
err_open_out:
|
443
|
|
- usb_endpoint_close ( &ecm->in.ep );
|
444
|
|
- assert ( ecm->in.fill == 0 );
|
|
369
|
+ usb_endpoint_close ( &ecm->in );
|
445
|
370
|
err_open_in:
|
446
|
371
|
usb_set_interface ( usb, ecm->data, 0 );
|
447
|
372
|
err_set_interface:
|
|
@@ -457,9 +382,8 @@ static void ecm_data_close ( struct ecm_device *ecm ) {
|
457
|
382
|
struct usb_device *usb = ecm->usb;
|
458
|
383
|
|
459
|
384
|
/* Close endpoints */
|
460
|
|
- usb_endpoint_close ( &ecm->out.ep );
|
461
|
|
- usb_endpoint_close ( &ecm->in.ep );
|
462
|
|
- assert ( ecm->in.fill == 0 );
|
|
385
|
+ usb_endpoint_close ( &ecm->out );
|
|
386
|
+ usb_endpoint_close ( &ecm->in );
|
463
|
387
|
|
464
|
388
|
/* Reset data interface */
|
465
|
389
|
usb_set_interface ( usb, ecm->data, 0 );
|
|
@@ -555,15 +479,18 @@ static int ecm_transmit ( struct net_device *netdev,
|
555
|
479
|
*/
|
556
|
480
|
static void ecm_poll ( struct net_device *netdev ) {
|
557
|
481
|
struct ecm_device *ecm = netdev->priv;
|
|
482
|
+ int rc;
|
558
|
483
|
|
559
|
484
|
/* Poll USB bus */
|
560
|
485
|
usb_poll ( ecm->bus );
|
561
|
486
|
|
562
|
|
- /* Refill interrupt ring */
|
563
|
|
- ecm_rx_refill ( ecm, &ecm->intr );
|
|
487
|
+ /* Refill interrupt endpoint */
|
|
488
|
+ if ( ( rc = usb_refill ( &ecm->intr ) ) != 0 )
|
|
489
|
+ netdev_rx_err ( netdev, NULL, rc );
|
564
|
490
|
|
565
|
|
- /* Refill bulk IN ring */
|
566
|
|
- ecm_rx_refill ( ecm, &ecm->in );
|
|
491
|
+ /* Refill bulk IN endpoint */
|
|
492
|
+ if ( ( rc = usb_refill ( &ecm->in ) ) != 0 )
|
|
493
|
+ netdev_rx_err ( netdev, NULL, rc );
|
567
|
494
|
}
|
568
|
495
|
|
569
|
496
|
/** CDC-ECM network device operations */
|
|
@@ -611,9 +538,11 @@ static int ecm_probe ( struct usb_function *func,
|
611
|
538
|
ecm->usb = usb;
|
612
|
539
|
ecm->bus = usb->port->hub->bus;
|
613
|
540
|
ecm->netdev = netdev;
|
614
|
|
- usb_endpoint_init ( &ecm->intr.ep, usb, &ecm_intr_operations );
|
615
|
|
- usb_endpoint_init ( &ecm->in.ep, usb, &ecm_in_operations );
|
616
|
|
- usb_endpoint_init ( &ecm->out.ep, usb, &ecm_out_operations );
|
|
541
|
+ usb_endpoint_init ( &ecm->intr, usb, &ecm_intr_operations );
|
|
542
|
+ usb_endpoint_init ( &ecm->in, usb, &ecm_in_operations );
|
|
543
|
+ usb_endpoint_init ( &ecm->out, usb, &ecm_out_operations );
|
|
544
|
+ usb_refill_init ( &ecm->intr, 0, ECM_INTR_MAX_FILL );
|
|
545
|
+ usb_refill_init ( &ecm->in, ECM_IN_MTU, ECM_IN_MAX_FILL );
|
617
|
546
|
DBGC ( ecm, "ECM %p on %s\n", ecm, func->name );
|
618
|
547
|
|
619
|
548
|
/* Identify interfaces */
|
|
@@ -644,27 +573,23 @@ static int ecm_probe ( struct usb_function *func,
|
644
|
573
|
}
|
645
|
574
|
|
646
|
575
|
/* Describe interrupt endpoint */
|
647
|
|
- if ( ( rc = usb_endpoint_described ( &ecm->intr.ep, config, comms,
|
|
576
|
+ if ( ( rc = usb_endpoint_described ( &ecm->intr, config, comms,
|
648
|
577
|
USB_INTERRUPT, 0 ) ) != 0 ) {
|
649
|
578
|
DBGC ( ecm, "ECM %p could not describe interrupt endpoint: "
|
650
|
579
|
"%s\n", ecm, strerror ( rc ) );
|
651
|
580
|
goto err_interrupt;
|
652
|
581
|
}
|
653
|
|
- ecm->intr.mtu = ecm->intr.ep.mtu;
|
654
|
|
- ecm->intr.max = ECM_INTR_MAX_FILL;
|
655
|
582
|
|
656
|
583
|
/* Describe bulk IN endpoint */
|
657
|
|
- if ( ( rc = usb_endpoint_described ( &ecm->in.ep, config, data,
|
|
584
|
+ if ( ( rc = usb_endpoint_described ( &ecm->in, config, data,
|
658
|
585
|
USB_BULK_IN, 0 ) ) != 0 ) {
|
659
|
586
|
DBGC ( ecm, "ECM %p could not describe bulk IN endpoint: "
|
660
|
587
|
"%s\n", ecm, strerror ( rc ) );
|
661
|
588
|
goto err_bulk_in;
|
662
|
589
|
}
|
663
|
|
- ecm->in.mtu = ECM_IN_MTU;
|
664
|
|
- ecm->in.max = ECM_IN_MAX_FILL;
|
665
|
590
|
|
666
|
591
|
/* Describe bulk OUT endpoint */
|
667
|
|
- if ( ( rc = usb_endpoint_described ( &ecm->out.ep, config, data,
|
|
592
|
+ if ( ( rc = usb_endpoint_described ( &ecm->out, config, data,
|
668
|
593
|
USB_BULK_OUT, 0 ) ) != 0 ) {
|
669
|
594
|
DBGC ( ecm, "ECM %p could not describe bulk OUT endpoint: "
|
670
|
595
|
"%s\n", ecm, strerror ( rc ) );
|