|
@@ -418,6 +418,7 @@ static void undinet_poll ( struct net_device *netdev ) {
|
418
|
418
|
struct io_buffer *iobuf = NULL;
|
419
|
419
|
size_t len;
|
420
|
420
|
size_t frag_len;
|
|
421
|
+ size_t max_frag_len;
|
421
|
422
|
int rc;
|
422
|
423
|
|
423
|
424
|
if ( ! undinic->isr_processing ) {
|
|
@@ -446,6 +447,14 @@ static void undinet_poll ( struct net_device *netdev ) {
|
446
|
447
|
/* Packet fragment received */
|
447
|
448
|
len = undi_isr.FrameLength;
|
448
|
449
|
frag_len = undi_isr.BufferLength;
|
|
450
|
+ if ( ( len == 0 ) || ( len < frag_len ) ) {
|
|
451
|
+ /* Don't laugh. VMWare does it. */
|
|
452
|
+ DBGC ( undinic, "UNDINIC %p reported insane "
|
|
453
|
+ "fragment (%zd of %zd bytes)\n",
|
|
454
|
+ undinic, frag_len, len );
|
|
455
|
+ netdev_rx_err ( netdev, NULL, -EINVAL );
|
|
456
|
+ break;
|
|
457
|
+ }
|
449
|
458
|
if ( ! iobuf )
|
450
|
459
|
iobuf = alloc_iob ( len );
|
451
|
460
|
if ( ! iobuf ) {
|
|
@@ -456,10 +465,13 @@ static void undinet_poll ( struct net_device *netdev ) {
|
456
|
465
|
netdev_rx_err ( netdev, NULL, -ENOMEM );
|
457
|
466
|
goto done;
|
458
|
467
|
}
|
459
|
|
- if ( frag_len > iob_tailroom ( iobuf ) ) {
|
460
|
|
- DBGC ( undinic, "UNDINIC %p fragment too "
|
461
|
|
- "large\n", undinic );
|
462
|
|
- frag_len = iob_tailroom ( iobuf );
|
|
468
|
+ max_frag_len = iob_tailroom ( iobuf );
|
|
469
|
+ if ( frag_len > max_frag_len ) {
|
|
470
|
+ DBGC ( undinic, "UNDINIC %p fragment too big "
|
|
471
|
+ "(%zd+%zd does not fit into %zd)\n",
|
|
472
|
+ undinic, iob_len ( iobuf ), frag_len,
|
|
473
|
+ ( iob_len ( iobuf ) + max_frag_len ) );
|
|
474
|
+ frag_len = max_frag_len;
|
463
|
475
|
}
|
464
|
476
|
copy_from_real ( iob_put ( iobuf, frag_len ),
|
465
|
477
|
undi_isr.Frame.segment,
|
|
@@ -473,6 +485,8 @@ static void undinet_poll ( struct net_device *netdev ) {
|
473
|
485
|
*/
|
474
|
486
|
if ( undinic->hacks & UNDI_HACK_EB54 )
|
475
|
487
|
--last_trigger_count;
|
|
488
|
+ /** HACK: effective RX quota of 1 */
|
|
489
|
+ goto done;
|
476
|
490
|
}
|
477
|
491
|
break;
|
478
|
492
|
case PXENV_UNDI_ISR_OUT_DONE:
|
|
@@ -491,8 +505,9 @@ static void undinet_poll ( struct net_device *netdev ) {
|
491
|
505
|
|
492
|
506
|
done:
|
493
|
507
|
if ( iobuf ) {
|
494
|
|
- DBGC ( undinic, "UNDINIC %p returned incomplete packet\n",
|
495
|
|
- undinic );
|
|
508
|
+ DBGC ( undinic, "UNDINIC %p returned incomplete packet "
|
|
509
|
+ "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
|
|
510
|
+ ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
|
496
|
511
|
netdev_rx_err ( netdev, iobuf, -EINVAL );
|
497
|
512
|
}
|
498
|
513
|
}
|