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; | ... | ... |