Revision 1b0009db hw/e1000.c

b/hw/e1000.c
105 105
        char tse;
106 106
        char ip;
107 107
        char tcp;
108
        char cptse;     // current packet tse bit
108 109
    } tx;
109 110

  
110 111
    struct {
......
308 309
    unsigned int frames = s->tx.tso_frames, css, sofar, n;
309 310
    struct e1000_tx *tp = &s->tx;
310 311

  
311
    if (tp->tse) {
312
    if (tp->tse && tp->cptse) {
312 313
        css = tp->ipcss;
313 314
        DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
314 315
               frames, tp->size, css);
......
382 383
            tp->tucso = tp->tucss + (tp->tcp ? 16 : 6);
383 384
        }
384 385
        return;
385
    } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D))
386
    } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
387
        // data descriptor
386 388
        tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
389
        tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
390
    } else
391
        // legacy descriptor
392
        tp->cptse = 0;
387 393

  
388 394
    addr = le64_to_cpu(dp->buffer_addr);
389
    if (tp->tse) {
395
    if (tp->tse && tp->cptse) {
390 396
        hdr = tp->hdr_len;
391 397
        msh = hdr + tp->mss;
398
        do {
399
            bytes = split_size;
400
            if (tp->size + bytes > msh)
401
                bytes = msh - tp->size;
402
            cpu_physical_memory_read(addr, tp->data + tp->size, bytes);
403
            if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
404
                memmove(tp->header, tp->data, hdr);
405
            tp->size = sz;
406
            addr += bytes;
407
            if (sz == msh) {
408
                xmit_seg(s);
409
                memmove(tp->data, tp->header, hdr);
410
                tp->size = hdr;
411
            }
412
        } while (split_size -= bytes);
413
    } else if (!tp->tse && tp->cptse) {
414
        // context descriptor TSE is not set, while data descriptor TSE is set
415
        DBGOUT(TXERR, "TCP segmentaion Error\n");
416
    } else {
417
        cpu_physical_memory_read(addr, tp->data + tp->size, split_size);
418
        tp->size += split_size;
392 419
    }
393
    do {
394
        bytes = split_size;
395
        if (tp->size + bytes > msh)
396
            bytes = msh - tp->size;
397
        cpu_physical_memory_read(addr, tp->data + tp->size, bytes);
398
        if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
399
            memmove(tp->header, tp->data, hdr);
400
        tp->size = sz;
401
        addr += bytes;
402
        if (sz == msh) {
403
            xmit_seg(s);
404
            memmove(tp->data, tp->header, hdr);
405
            tp->size = hdr;
406
        }
407
    } while (split_size -= bytes);
408 420

  
409 421
    if (!(txd_lower & E1000_TXD_CMD_EOP))
410 422
        return;
411
    if (tp->size > hdr)
423
    if (!(tp->tse && tp->cptse && tp->size < hdr))
412 424
        xmit_seg(s);
413 425
    tp->tso_frames = 0;
414 426
    tp->sum_needed = 0;
415 427
    tp->size = 0;
428
    tp->cptse = 0;
416 429
}
417 430

  
418 431
static uint32_t

Also available in: Unified diff