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,6 +318,8 @@ static inline void channel_start(struct fs_dma_ctrl *ctrl, int c) | ||
| 318 | ctrl->channels[c].state = RUNNING; | 318 | ctrl->channels[c].state = RUNNING; |
| 319 | } else | 319 | } else |
| 320 | printf("WARNING: starting DMA ch %d with no client\n", c); | 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 | static void channel_continue(struct fs_dma_ctrl *ctrl, int c) | 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,13 +393,16 @@ static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c) | ||
| 391 | qemu_irq_lower(ctrl->channels[c].irq[0]); | 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 | uint32_t len; | 398 | uint32_t len; |
| 397 | uint32_t saved_data_buf; | 399 | uint32_t saved_data_buf; |
| 398 | unsigned char buf[2 * 1024]; | 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 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); | 406 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); |
| 402 | 407 | ||
| 403 | D(printf("ch=%d buf=%x after=%x saved_data_buf=%x\n", | 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,7 +471,8 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) | ||
| 466 | D(dump_d(c, &ctrl->channels[c].current_d)); | 471 | D(dump_d(c, &ctrl->channels[c].current_d)); |
| 467 | } | 472 | } |
| 468 | ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf; | 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 | static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, | 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,11 +545,14 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, | ||
| 539 | return len; | 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 | ctrl->channels[c].client->client.pull( | 551 | ctrl->channels[c].client->client.pull( |
| 546 | ctrl->channels[c].client->client.opaque); | 552 | ctrl->channels[c].client->client.opaque); |
| 553 | + return 1; | ||
| 554 | + } else | ||
| 555 | + return 0; | ||
| 547 | } | 556 | } |
| 548 | 557 | ||
| 549 | static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr) | 558 | static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr) |
| @@ -673,7 +682,7 @@ static CPUWriteMemoryFunc *dma_write[] = { | @@ -673,7 +682,7 @@ static CPUWriteMemoryFunc *dma_write[] = { | ||
| 673 | &dma_writel, | 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 | struct fs_dma_ctrl *ctrl = opaque; | 687 | struct fs_dma_ctrl *ctrl = opaque; |
| 679 | int i; | 688 | int i; |
| @@ -685,13 +694,14 @@ static void etraxfs_dmac_run(void *opaque) | @@ -685,13 +694,14 @@ static void etraxfs_dmac_run(void *opaque) | ||
| 685 | { | 694 | { |
| 686 | if (ctrl->channels[i].state == RUNNING) | 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 | int etraxfs_dmac_input(struct etraxfs_dma_client *client, | 707 | int etraxfs_dmac_input(struct etraxfs_dma_client *client, |
| @@ -722,9 +732,13 @@ void etraxfs_dmac_connect_client(void *opaque, int c, | @@ -722,9 +732,13 @@ void etraxfs_dmac_connect_client(void *opaque, int c, | ||
| 722 | static void DMA_run(void *opaque) | 732 | static void DMA_run(void *opaque) |
| 723 | { | 733 | { |
| 724 | struct fs_dma_ctrl *etraxfs_dmac = opaque; | 734 | struct fs_dma_ctrl *etraxfs_dmac = opaque; |
| 735 | + int p = 1; | ||
| 736 | + | ||
| 725 | if (vm_running) | 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 | void *etraxfs_dmac_init(CPUState *env, | 744 | void *etraxfs_dmac_init(CPUState *env, |
| @@ -738,7 +752,6 @@ void *etraxfs_dmac_init(CPUState *env, | @@ -738,7 +752,6 @@ void *etraxfs_dmac_init(CPUState *env, | ||
| 738 | return NULL; | 752 | return NULL; |
| 739 | 753 | ||
| 740 | ctrl->bh = qemu_bh_new(DMA_run, ctrl); | 754 | ctrl->bh = qemu_bh_new(DMA_run, ctrl); |
| 741 | - qemu_bh_schedule_idle(ctrl->bh); | ||
| 742 | 755 | ||
| 743 | ctrl->base = base; | 756 | ctrl->base = base; |
| 744 | ctrl->env = env; | 757 | ctrl->env = env; |