Commit 1ab5f75cf04175ec430ba6d2bbe1e522d70a2498
1 parent
9eee9a5d
ETRAX-FS: Don't schedule DMA processing without active channels.
Avoid scheduling DMA processing when all channels are stopped or at end-of-list. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5720 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
27 additions
and
14 deletions
hw/etraxfs_dma.c
| ... | ... | @@ -318,6 +318,8 @@ static inline void channel_start(struct fs_dma_ctrl *ctrl, int c) |
| 318 | 318 | ctrl->channels[c].state = RUNNING; |
| 319 | 319 | } else |
| 320 | 320 | printf("WARNING: starting DMA ch %d with no client\n", c); |
| 321 | + | |
| 322 | + qemu_bh_schedule_idle(ctrl->bh); | |
| 321 | 323 | } |
| 322 | 324 | |
| 323 | 325 | static void channel_continue(struct fs_dma_ctrl *ctrl, int c) |
| ... | ... | @@ -391,13 +393,16 @@ static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c) |
| 391 | 393 | qemu_irq_lower(ctrl->channels[c].irq[0]); |
| 392 | 394 | } |
| 393 | 395 | |
| 394 | -static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) | |
| 396 | +static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) | |
| 395 | 397 | { |
| 396 | 398 | uint32_t len; |
| 397 | 399 | uint32_t saved_data_buf; |
| 398 | 400 | unsigned char buf[2 * 1024]; |
| 399 | 401 | |
| 400 | - while (ctrl->channels[c].eol != 1) { | |
| 402 | + if (ctrl->channels[c].eol) | |
| 403 | + return 0; | |
| 404 | + | |
| 405 | + do { | |
| 401 | 406 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); |
| 402 | 407 | |
| 403 | 408 | D(printf("ch=%d buf=%x after=%x saved_data_buf=%x\n", |
| ... | ... | @@ -466,7 +471,8 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) |
| 466 | 471 | D(dump_d(c, &ctrl->channels[c].current_d)); |
| 467 | 472 | } |
| 468 | 473 | ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf; |
| 469 | - } | |
| 474 | + } while (!ctrl->channels[c].eol); | |
| 475 | + return 1; | |
| 470 | 476 | } |
| 471 | 477 | |
| 472 | 478 | static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, |
| ... | ... | @@ -539,11 +545,14 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, |
| 539 | 545 | return len; |
| 540 | 546 | } |
| 541 | 547 | |
| 542 | -static inline void channel_in_run(struct fs_dma_ctrl *ctrl, int c) | |
| 548 | +static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c) | |
| 543 | 549 | { |
| 544 | - if (ctrl->channels[c].client->client.pull) | |
| 550 | + if (ctrl->channels[c].client->client.pull) { | |
| 545 | 551 | ctrl->channels[c].client->client.pull( |
| 546 | 552 | ctrl->channels[c].client->client.opaque); |
| 553 | + return 1; | |
| 554 | + } else | |
| 555 | + return 0; | |
| 547 | 556 | } |
| 548 | 557 | |
| 549 | 558 | static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr) |
| ... | ... | @@ -673,7 +682,7 @@ static CPUWriteMemoryFunc *dma_write[] = { |
| 673 | 682 | &dma_writel, |
| 674 | 683 | }; |
| 675 | 684 | |
| 676 | -static void etraxfs_dmac_run(void *opaque) | |
| 685 | +static int etraxfs_dmac_run(void *opaque) | |
| 677 | 686 | { |
| 678 | 687 | struct fs_dma_ctrl *ctrl = opaque; |
| 679 | 688 | int i; |
| ... | ... | @@ -685,13 +694,14 @@ static void etraxfs_dmac_run(void *opaque) |
| 685 | 694 | { |
| 686 | 695 | if (ctrl->channels[i].state == RUNNING) |
| 687 | 696 | { |
| 688 | - p++; | |
| 689 | - if (ctrl->channels[i].input) | |
| 690 | - channel_in_run(ctrl, i); | |
| 691 | - else | |
| 692 | - channel_out_run(ctrl, i); | |
| 697 | + if (ctrl->channels[i].input) { | |
| 698 | + p += channel_in_run(ctrl, i); | |
| 699 | + } else { | |
| 700 | + p += channel_out_run(ctrl, i); | |
| 701 | + } | |
| 693 | 702 | } |
| 694 | 703 | } |
| 704 | + return p; | |
| 695 | 705 | } |
| 696 | 706 | |
| 697 | 707 | int etraxfs_dmac_input(struct etraxfs_dma_client *client, |
| ... | ... | @@ -722,9 +732,13 @@ void etraxfs_dmac_connect_client(void *opaque, int c, |
| 722 | 732 | static void DMA_run(void *opaque) |
| 723 | 733 | { |
| 724 | 734 | struct fs_dma_ctrl *etraxfs_dmac = opaque; |
| 735 | + int p = 1; | |
| 736 | + | |
| 725 | 737 | if (vm_running) |
| 726 | - etraxfs_dmac_run(etraxfs_dmac); | |
| 727 | - qemu_bh_schedule_idle(etraxfs_dmac->bh); | |
| 738 | + p = etraxfs_dmac_run(etraxfs_dmac); | |
| 739 | + | |
| 740 | + if (p) | |
| 741 | + qemu_bh_schedule_idle(etraxfs_dmac->bh); | |
| 728 | 742 | } |
| 729 | 743 | |
| 730 | 744 | void *etraxfs_dmac_init(CPUState *env, |
| ... | ... | @@ -738,7 +752,6 @@ void *etraxfs_dmac_init(CPUState *env, |
| 738 | 752 | return NULL; |
| 739 | 753 | |
| 740 | 754 | ctrl->bh = qemu_bh_new(DMA_run, ctrl); |
| 741 | - qemu_bh_schedule_idle(ctrl->bh); | |
| 742 | 755 | |
| 743 | 756 | ctrl->base = base; |
| 744 | 757 | ctrl->env = env; | ... | ... |